1
0
Fork 0
mirror of synced 2024-09-08 05:31:47 +12:00

Add new long form text cell

This commit is contained in:
Andrew Kingston 2023-03-14 09:44:21 +00:00
parent aefdfabe39
commit 125febdd5a
8 changed files with 144 additions and 18 deletions

View file

@ -2,23 +2,36 @@
import { getContext, onMount } from "svelte"
import { get } from "svelte/store"
const { rows, rand, selectedCellId, columns, selectedCellRow, stickyColumn, selectedCellAPI } =
getContext("sheet")
const {
rows,
selectedCellId,
columns,
selectedCellRow,
stickyColumn,
selectedCellAPI,
} = getContext("sheet")
const handleKeyDown = e => {
const api = get(selectedCellAPI)
if (!api) {
return
}
// Always capture escape and blur any selected cell
// Always intercept certain key presses
if (e.key === "Escape") {
api?.blur()
api.blur()
} else if (e.key === "Tab") {
api.blur()
changeSelectedColumn(1)
}
// Pass the key event to the selected cell and let it decide whether to
// capture it or not
const handled = api?.onKeyDown?.(e)
const handled = api.onKeyDown?.(e)
if (handled) {
return
}
e.preventDefault()
// Handle the key ourselves
switch (e.key) {
@ -39,7 +52,7 @@
break
case "Enter":
focusSelectedCell()
break;
break
}
}

View file

@ -46,6 +46,7 @@
// Handles a wheel even and updates the scroll offsets
const handleWheel = e => {
console.log("wheel scrol!")
e.preventDefault()
const modifier = e.ctrlKey || e.metaKey
let x = modifier ? e.deltaY : e.deltaX

View file

@ -0,0 +1 @@
<div>[MISSING]</div>

View file

@ -2,7 +2,7 @@
import { getContext } from "svelte"
import SheetCell from "./SheetCell.svelte"
import { Icon, Popover, Menu, MenuItem } from "@budibase/bbui"
import { getIconForField } from "../utils"
import { getColumnIcon } from "../utils"
export let column
export let idx
@ -17,7 +17,7 @@
renderedColumns,
dispatch,
config,
ui
ui,
} = getContext("sheet")
let anchor
@ -99,7 +99,7 @@
>
<Icon
size="S"
name={getIconForField(column)}
name={getColumnIcon(column)}
color={`var(--spectrum-global-color-gray-600)`}
/>
<div class="name">

View file

@ -0,0 +1,101 @@
<script>
import { onMount, tick } from "svelte"
export let value
export let selected = false
export let onChange
export let readonly = false
export let api
let textarea
let isOpen = false
$: editable = selected && !readonly
$: {
if (!selected) {
isOpen = false
}
}
const handleChange = e => {
onChange(e.target.value)
console.log(e.target.value)
}
const onKeyDown = () => {
return isOpen
}
const open = async () => {
isOpen = true
await tick()
textarea.focus()
textarea.setSelectionRange(0, 0)
}
const close = () => {
textarea?.blur()
isOpen = false
}
onMount(() => {
api = {
focus: () => open(),
blur: () => close(),
onKeyDown,
}
})
</script>
{#if isOpen}
<textarea
bind:this={textarea}
value={value || ""}
on:change={handleChange}
on:wheel|stopPropagation
/>
{:else}
<div class="long-form-cell" on:click={editable ? open : null} class:editable>
<div class="value">
{value || ""}
</div>
</div>
{/if}
<style>
.long-form-cell {
flex: 1 1 auto;
padding: 0 var(--cell-padding);
align-self: stretch;
display: flex;
align-items: center;
overflow: hidden;
}
.long-form-cell.editable:hover {
cursor: text;
}
.value {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
textarea {
padding: var(--cell-padding);
margin: 0;
border: none;
background: var(--cell-background);
font-size: var(--cell-font-size);
font-family: var(--font-sans);
color: inherit;
position: absolute;
top: -1px;
left: -1px;
width: calc(100% + 100px);
height: calc(5 * var(--cell-height) + 1px);
border: var(--cell-border);
box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.15);
}
textarea:focus {
outline: none;
}
</style>

View file

@ -183,17 +183,18 @@
);
}
.options {
min-width: 100%;
min-width: calc(100% + 2px);
position: absolute;
top: 0;
left: 0;
top: -1px;
left: -1px;
display: flex;
flex-direction: column;
box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.15);
justify-content: flex-start;
align-items: stretch;
max-height: calc(6 * var(--cell-height) - 1px);
max-height: calc(5 * var(--cell-height) + 1px);
overflow-y: auto;
border: var(--cell-border);
}
.option {
flex: 0 0 var(--cell-height);

View file

@ -4,13 +4,22 @@ import MultiSelectCell from "./cells/MultiSelectCell.svelte"
import NumberCell from "./cells/NumberCell.svelte"
import RelationshipCell from "./cells/RelationshipCell.svelte"
import TextCell from "./cells/TextCell.svelte"
import BlankCell from "./cells/BlankCell.svelte"
import LongFormCell from "./cells/LongFormCell.svelte"
const TypeComponentMap = {
text: TextCell,
options: OptionsCell,
datetime: DateCell,
barcodeqr: BlankCell,
longform: LongFormCell,
array: MultiSelectCell,
number: NumberCell,
boolean: BlankCell,
attachment: BlankCell,
link: RelationshipCell,
formula: BlankCell,
json: BlankCell,
}
export const getCellRenderer = column => {
return TypeComponentMap[column?.schema?.type] || TextCell

View file

@ -5,10 +5,10 @@ export const getColor = (idx, opacity = 0.3) => {
return `hsla(${((idx + 1) * 222) % 360}, 90%, 75%, ${opacity})`
}
const DataTypeIconMap = {
const TypeIconMap = {
text: "Text",
options: "Dropdown",
datetime: "Date",
text: "Text",
barcodeqr: "Camera",
longform: "TextAlignLeft",
array: "Dropdown",
@ -20,7 +20,7 @@ const DataTypeIconMap = {
json: "Brackets",
}
export const getIconForField = field => {
const type = field.schema.type
return DataTypeIconMap[type] || "Text"
export const getColumnIcon = column => {
const type = column.schema.type
return TypeIconMap[type] || "Text"
}