@dou-ui/sheet 0.0.0-stage → 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/cell-types.js +20 -0
- package/dist/cell-types.js.map +1 -0
- package/dist/code/code-formula-bar.js +6 -0
- package/dist/code/code-formula-bar.js.map +1 -0
- package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js +192 -0
- package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/code/index.js +12 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code/language.js +51 -0
- package/dist/code/language.js.map +1 -0
- package/dist/code/style.d.ts +1 -0
- package/dist/code/style.js +2 -0
- package/dist/collaboration/anchor.js +143 -0
- package/dist/collaboration/anchor.js.map +1 -0
- package/dist/collaboration/index.js +770 -0
- package/dist/collaboration/index.js.map +1 -0
- package/dist/collaboration/peers.js +87 -0
- package/dist/collaboration/peers.js.map +1 -0
- package/dist/collaboration/shared.js +450 -0
- package/dist/collaboration/shared.js.map +1 -0
- package/dist/components/cell-panel.js +6 -0
- package/dist/components/cell-panel.js.map +1 -0
- package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/cell-renders.js +40 -0
- package/dist/components/cell-renders.js.map +1 -0
- package/dist/components/date-panel.js +6 -0
- package/dist/components/date-panel.js.map +1 -0
- package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js +48 -0
- package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/filter-panel.js +6 -0
- package/dist/components/filter-panel.js.map +1 -0
- package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js +259 -0
- package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-dialog.js +6 -0
- package/dist/components/format-dialog.js.map +1 -0
- package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js +432 -0
- package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-list.js +6 -0
- package/dist/components/format-list.js.map +1 -0
- package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js +187 -0
- package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-presets.js +97 -0
- package/dist/components/format-presets.js.map +1 -0
- package/dist/components/option-panel.js +6 -0
- package/dist/components/option-panel.js.map +1 -0
- package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js +117 -0
- package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-comment.js +6 -0
- package/dist/components/sheet-comment.js.map +1 -0
- package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-formula-bar.js +6 -0
- package/dist/components/sheet-formula-bar.js.map +1 -0
- package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js +124 -0
- package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-link.js +6 -0
- package/dist/components/sheet-link.js.map +1 -0
- package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js +249 -0
- package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-menu.js +6 -0
- package/dist/components/sheet-menu.js.map +1 -0
- package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js +115 -0
- package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-name-box.js +6 -0
- package/dist/components/sheet-name-box.js.map +1 -0
- package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js +91 -0
- package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-note.js +6 -0
- package/dist/components/sheet-note.js.map +1 -0
- package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-outline.js +6 -0
- package/dist/components/sheet-outline.js.map +1 -0
- package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js +237 -0
- package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-tabs.js +6 -0
- package/dist/components/sheet-tabs.js.map +1 -0
- package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js +487 -0
- package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-toolbar.js +6 -0
- package/dist/components/sheet-toolbar.js.map +1 -0
- package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js +1562 -0
- package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/validation-dialog.js +6 -0
- package/dist/components/validation-dialog.js.map +1 -0
- package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js +370 -0
- package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/context.js +12 -0
- package/dist/context.js.map +1 -0
- package/dist/core/address.js +256 -0
- package/dist/core/address.js.map +1 -0
- package/dist/core/axis.js +72 -0
- package/dist/core/axis.js.map +1 -0
- package/dist/core/cell-type.js +30 -0
- package/dist/core/cell-type.js.map +1 -0
- package/dist/core/clipboard.js +141 -0
- package/dist/core/clipboard.js.map +1 -0
- package/dist/core/commands.js +63 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/comments.js +74 -0
- package/dist/core/comments.js.map +1 -0
- package/dist/core/conditional.js +362 -0
- package/dist/core/conditional.js.map +1 -0
- package/dist/core/csv.js +191 -0
- package/dist/core/csv.js.map +1 -0
- package/dist/core/data.js +118 -0
- package/dist/core/data.js.map +1 -0
- package/dist/core/document.js +187 -0
- package/dist/core/document.js.map +1 -0
- package/dist/core/extension.js +60 -0
- package/dist/core/extension.js.map +1 -0
- package/dist/core/file.js +336 -0
- package/dist/core/file.js.map +1 -0
- package/dist/core/fill.js +153 -0
- package/dist/core/fill.js.map +1 -0
- package/dist/core/find.js +42 -0
- package/dist/core/find.js.map +1 -0
- package/dist/core/format.js +404 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/group.js +134 -0
- package/dist/core/group.js.map +1 -0
- package/dist/core/history.js +68 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/index.js +17 -0
- package/dist/core/link.js +34 -0
- package/dist/core/link.js.map +1 -0
- package/dist/core/merge.js +105 -0
- package/dist/core/merge.js.map +1 -0
- package/dist/core/model.js +48 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/nav.js +44 -0
- package/dist/core/nav.js.map +1 -0
- package/dist/core/paint.js +106 -0
- package/dist/core/paint.js.map +1 -0
- package/dist/core/plain-cell-types.js +54 -0
- package/dist/core/plain-cell-types.js.map +1 -0
- package/dist/core/protect.js +246 -0
- package/dist/core/protect.js.map +1 -0
- package/dist/core/selection.js +37 -0
- package/dist/core/selection.js.map +1 -0
- package/dist/core/transaction.js +1582 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/validation.js +135 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/core/versions.js +161 -0
- package/dist/core/versions.js.map +1 -0
- package/dist/export/color.js +36 -0
- package/dist/export/color.js.map +1 -0
- package/dist/export/draw.js +316 -0
- package/dist/export/draw.js.map +1 -0
- package/dist/export/index.js +390 -0
- package/dist/export/index.js.map +1 -0
- package/dist/formula/edit.js +210 -0
- package/dist/formula/edit.js.map +1 -0
- package/dist/formula/engine.js +526 -0
- package/dist/formula/engine.js.map +1 -0
- package/dist/formula/error.js +39 -0
- package/dist/formula/error.js.map +1 -0
- package/dist/formula/functions.js +1493 -0
- package/dist/formula/functions.js.map +1 -0
- package/dist/formula/help.js +408 -0
- package/dist/formula/help.js.map +1 -0
- package/dist/formula/index.js +7 -0
- package/dist/formula/parse.js +369 -0
- package/dist/formula/parse.js.map +1 -0
- package/dist/formula/values.js +123 -0
- package/dist/formula/values.js.map +1 -0
- package/dist/formulas.js +30 -0
- package/dist/formulas.js.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/locale.js +1312 -0
- package/dist/locale.js.map +1 -0
- package/dist/sheet.js +6 -0
- package/dist/sheet.js.map +1 -0
- package/dist/sheet.vue_vue_type_script_setup_true_lang.js +7166 -0
- package/dist/sheet.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +17 -0
- package/dist/types/cell-types.d.ts +2 -0
- package/dist/types/code/code-formula-bar.vue.d.ts +3 -0
- package/dist/types/code/index.d.ts +12 -0
- package/dist/types/code/language.d.ts +13 -0
- package/dist/types/collaboration/anchor.d.ts +65 -0
- package/dist/types/collaboration/index.d.ts +59 -0
- package/dist/types/collaboration/peers.d.ts +21 -0
- package/dist/types/collaboration/shared.d.ts +75 -0
- package/dist/types/components/cell-panel.vue.d.ts +20 -0
- package/dist/types/components/cell-renders.d.ts +9 -0
- package/dist/types/components/date-panel.vue.d.ts +9 -0
- package/dist/types/components/filter-panel.vue.d.ts +21 -0
- package/dist/types/components/format-dialog.vue.d.ts +24 -0
- package/dist/types/components/format-list.vue.d.ts +25 -0
- package/dist/types/components/format-presets.d.ts +30 -0
- package/dist/types/components/option-panel.vue.d.ts +13 -0
- package/dist/types/components/sheet-comment.vue.d.ts +29 -0
- package/dist/types/components/sheet-formula-bar.vue.d.ts +3 -0
- package/dist/types/components/sheet-link.vue.d.ts +32 -0
- package/dist/types/components/sheet-menu.vue.d.ts +20 -0
- package/dist/types/components/sheet-name-box.vue.d.ts +3 -0
- package/dist/types/components/sheet-note.vue.d.ts +22 -0
- package/dist/types/components/sheet-outline.vue.d.ts +36 -0
- package/dist/types/components/sheet-tabs.vue.d.ts +9 -0
- package/dist/types/components/sheet-toolbar.vue.d.ts +11 -0
- package/dist/types/components/validation-dialog.vue.d.ts +25 -0
- package/dist/types/context.d.ts +189 -0
- package/dist/types/core/address.d.ts +109 -0
- package/dist/types/core/axis.d.ts +23 -0
- package/dist/types/core/cell-type.d.ts +157 -0
- package/dist/types/core/clipboard.d.ts +48 -0
- package/dist/types/core/commands.d.ts +76 -0
- package/dist/types/core/comments.d.ts +22 -0
- package/dist/types/core/conditional.d.ts +114 -0
- package/dist/types/core/csv.d.ts +93 -0
- package/dist/types/core/data.d.ts +26 -0
- package/dist/types/core/document.d.ts +49 -0
- package/dist/types/core/extension.d.ts +177 -0
- package/dist/types/core/file.d.ts +301 -0
- package/dist/types/core/fill.d.ts +23 -0
- package/dist/types/core/find.d.ts +39 -0
- package/dist/types/core/format.d.ts +47 -0
- package/dist/types/core/group.d.ts +76 -0
- package/dist/types/core/history.d.ts +27 -0
- package/dist/types/core/index.d.ts +33 -0
- package/dist/types/core/link.d.ts +14 -0
- package/dist/types/core/merge.d.ts +26 -0
- package/dist/types/core/model.d.ts +363 -0
- package/dist/types/core/nav.d.ts +15 -0
- package/dist/types/core/paint.d.ts +19 -0
- package/dist/types/core/plain-cell-types.d.ts +6 -0
- package/dist/types/core/protect.d.ts +34 -0
- package/dist/types/core/selection.d.ts +25 -0
- package/dist/types/core/transaction.d.ts +470 -0
- package/dist/types/core/validation.d.ts +55 -0
- package/dist/types/core/versions.d.ts +38 -0
- package/dist/types/export/color.d.ts +7 -0
- package/dist/types/export/draw.d.ts +98 -0
- package/dist/types/export/index.d.ts +47 -0
- package/dist/types/formula/edit.d.ts +62 -0
- package/dist/types/formula/engine.d.ts +99 -0
- package/dist/types/formula/error.d.ts +30 -0
- package/dist/types/formula/functions.d.ts +62 -0
- package/dist/types/formula/help.d.ts +12 -0
- package/dist/types/formula/index.d.ts +13 -0
- package/dist/types/formula/parse.d.ts +92 -0
- package/dist/types/formula/values.d.ts +65 -0
- package/dist/types/formulas.d.ts +32 -0
- package/dist/types/index.d.ts +225 -0
- package/dist/types/locale.d.ts +531 -0
- package/dist/types/sheet.vue.d.ts +60 -0
- package/dist/types/types.d.ts +498 -0
- package/dist/types/use-comments.d.ts +47 -0
- package/dist/types/use-messages.d.ts +7 -0
- package/dist/use-comments.js +130 -0
- package/dist/use-comments.js.map +1 -0
- package/dist/use-messages.js +29 -0
- package/dist/use-messages.js.map +1 -0
- package/package.json +93 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-dialog.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","_unref","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","_createVNode","_withKeys","_withModifiers","_createElementBlock","_Fragment","_createElementVNode"],"sources":["../../src/components/validation-dialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n DouButton,\n DouCheckbox,\n DouDialog,\n DouForm,\n DouFormItem,\n DouInput,\n DouSelect,\n} from 'dou-ui'\nimport { computed, ref, useTemplateRef, watch } from 'vue'\nimport { readRuleRange, ruleRangeText } from '../core/conditional'\nimport { optionOf } from '../core/cell-type'\nimport type { SheetCondition, SheetValidation, SheetValue } from '../core/model'\nimport type { SheetMessages } from '../locale'\n\n/*\n * Sets the validation rule of some cells: what they may hold, the hint\n * shown while one is active, and what is said when a value doesn't fit.\n */\n\nconst props = defineProps<{\n rule: SheetValidation\n /** Whether the rule is one the sheet has, which can be removed. */\n editing: boolean\n messages: SheetMessages\n}>()\nconst open = defineModel<boolean>('open', { required: true })\nconst emit = defineEmits<{ apply: [rule: SheetValidation]; remove: []; closed: [] }>()\n\nconst m = computed(() => props.messages.validation)\n\ntype Kind = keyof SheetMessages['validation']['kinds']\ntype Op = SheetCondition['op'] | 'any'\nconst NUMBER_OPS: Op[] = ['any', 'between', 'notBetween', 'eq', 'ne', 'gt', 'ge', 'lt', 'le']\nconst TEXT_OPS: Op[] = ['contains', 'notContains', 'begins', 'ends', 'eq', 'ne']\n\nconst target = ref('')\nconst kind = ref<Kind>('list')\nconst options = ref('')\nconst op = ref<Op>('between')\nconst value = ref('')\nconst to = ref('')\nconst formula = ref('')\nconst prompt = ref('')\nconst message = ref('')\nconst strict = ref(true)\nconst tried = ref(false)\n\nconst text = (v: SheetValue | undefined) => (v == null ? '' : String(v))\n/** A list's options as typed: its values separated by commas, or its reference. */\nfunction listText(list: Extract<SheetValidation, { list: unknown }>['list']) {\n return typeof list === 'string' ? list : list.map((o) => text(optionOf(o).value)).join(', ')\n}\n\nfunction kindOf(rule: SheetValidation): Kind {\n if ('list' in rule) return 'list'\n if ('formula' in rule) return 'formula'\n if (rule.integer) return 'integer'\n const { op: o, value: v, to: t } = rule.when\n if (typeof v === 'number' || typeof t === 'number' || o === 'notBlank') return 'number'\n return TEXT_OPS.includes(o) ? 'text' : 'number'\n}\n\nwatch(open, (now) => {\n if (!now) return\n const r = props.rule\n target.value = ruleRangeText(r.range)\n kind.value = kindOf(r)\n options.value = 'list' in r ? listText(r.list) : ''\n const when = 'when' in r ? r.when : undefined\n op.value = !when ? 'between' : when.op === 'notBlank' && kind.value !== 'text' ? 'any' : when.op\n value.value = text(when?.value)\n to.value = text(when?.to)\n formula.value = 'formula' in r ? r.formula : ''\n prompt.value = r.prompt ?? ''\n message.value = r.message ?? ''\n strict.value = r.strict !== false\n tried.value = false\n})\n\n// a condition that doesn't suit the kind picked starts over\nwatch(kind, (now) => {\n const ops = now === 'text' ? TEXT_OPS : NUMBER_OPS\n if (!ops.includes(op.value)) op.value = now === 'text' ? 'contains' : 'between'\n})\n\nconst kindOptions = computed(() =>\n (Object.keys(m.value.kinds) as Kind[]).map((k) => ({ value: k, label: m.value.kinds[k] })),\n)\nconst opOptions = computed(() =>\n (kind.value === 'text' ? TEXT_OPS : NUMBER_OPS).map((o) => ({\n value: o,\n label: o === 'any' ? m.value.any : props.messages.ops[o],\n })),\n)\n\nconst numeric = computed(() => kind.value === 'number' || kind.value === 'integer')\nconst needsValue = computed(() => (kind.value === 'text' || numeric.value) && op.value !== 'any')\nconst needsTo = computed(() => op.value === 'between' || op.value === 'notBetween')\n\n/** A number typed in a field, or `null`. */\nfunction numberOf(input: string) {\n const n = Number(input.trim().replace(/,/g, ''))\n return input.trim() && Number.isFinite(n) ? n : null\n}\n/** A list option as typed: a number when it reads as one. */\nfunction operand(input: string): SheetValue {\n return numberOf(input) ?? input.trim()\n}\n\nconst rangeOk = computed(() => readRuleRange(target.value) != null)\nconst optionsOk = computed(\n () => kind.value !== 'list' || options.value.trim().replace(/^=/, '') !== '',\n)\nconst fieldOk = (input: string) => (numeric.value ? numberOf(input) != null : input.trim() !== '')\nconst valueOk = computed(\n () => !needsValue.value || (fieldOk(value.value) && (!needsTo.value || fieldOk(to.value))),\n)\nconst formulaOk = computed(\n () => kind.value !== 'formula' || formula.value.trim().replace(/^=/, '') !== '',\n)\n\nfunction result(): SheetValidation {\n const base: Pick<SheetValidation, 'range' | 'strict' | 'prompt' | 'message'> = {\n range: readRuleRange(target.value)!,\n }\n if (!strict.value) base.strict = false\n if (prompt.value.trim()) base.prompt = prompt.value.trim()\n if (message.value.trim()) base.message = message.value.trim()\n const r = props.rule\n switch (kind.value) {\n case 'list': {\n const typed = options.value.trim()\n // options left as they were keep their tones\n if ('list' in r && typed === listText(r.list)) return { ...base, list: r.list }\n if (typed.startsWith('=')) return { ...base, list: typed }\n const list = typed\n .split(/[,,\\n]/)\n .map((part) => part.trim())\n .filter(Boolean)\n .map(operand)\n return { ...base, list }\n }\n case 'formula': {\n const body = formula.value.trim()\n return { ...base, formula: body.startsWith('=') ? body : `=${body}` }\n }\n default: {\n const read = (input: string) => (numeric.value ? numberOf(input)! : input.trim())\n const when: SheetCondition =\n op.value === 'any' ? { op: 'notBlank' } : { op: op.value, value: read(value.value) }\n if (needsValue.value && needsTo.value) when.to = read(to.value)\n return kind.value === 'integer' ? { ...base, when, integer: true } : { ...base, when }\n }\n }\n}\n\nconst rangeInput = useTemplateRef<InstanceType<typeof DouInput>>('rangeInput')\nconst optionsInput = useTemplateRef<InstanceType<typeof DouInput>>('optionsInput')\nfunction focusFirst() {\n ;(optionsInput.value ?? rangeInput.value)?.focus()\n}\n\nfunction apply() {\n tried.value = true\n if (!rangeOk.value || !optionsOk.value || !valueOk.value || !formulaOk.value) return\n emit('apply', result())\n open.value = false\n}\nfunction remove() {\n emit('remove')\n open.value = false\n}\n</script>\n\n<template>\n <DouDialog\n v-model:open=\"open\"\n :title=\"m.title\"\n :width=\"440\"\n @opened=\"focusFirst\"\n @closed=\"emit('closed')\"\n >\n <DouForm layout=\"vertical\" class=\"dou-sheet-format\" @submit=\"apply\">\n <DouFormItem :label=\"m.range\" :error=\"tried && !rangeOk ? m.invalidRange : undefined\">\n <DouInput ref=\"rangeInput\" v-model=\"target\" :invalid=\"tried && !rangeOk\" />\n </DouFormItem>\n <DouFormItem :label=\"m.allow\">\n <DouSelect v-model=\"kind\" :options=\"kindOptions\" />\n </DouFormItem>\n <DouFormItem\n v-if=\"kind === 'list'\"\n :label=\"m.options\"\n :help=\"m.optionsHelp\"\n :error=\"tried && !optionsOk ? m.needOptions : undefined\"\n >\n <DouInput\n ref=\"optionsInput\"\n v-model=\"options\"\n :invalid=\"tried && !optionsOk\"\n @keydown.enter.prevent=\"apply\"\n />\n </DouFormItem>\n <DouFormItem\n v-else-if=\"kind === 'formula'\"\n :label=\"m.formula\"\n :help=\"m.formulaHelp\"\n :error=\"tried && !formulaOk ? m.needFormula : undefined\"\n >\n <DouInput\n v-model=\"formula\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n :invalid=\"tried && !formulaOk\"\n @keydown.enter.prevent=\"apply\"\n />\n </DouFormItem>\n <template v-else>\n <DouFormItem :label=\"m.condition\">\n <DouSelect v-model=\"op\" :options=\"opOptions\" />\n </DouFormItem>\n <DouFormItem\n v-if=\"needsValue\"\n :label=\"m.value\"\n :error=\"tried && !valueOk ? m.needValue : undefined\"\n >\n <div class=\"dou-sheet-format__values\">\n <DouInput\n v-model=\"value\"\n :aria-label=\"m.value\"\n :inputmode=\"numeric ? 'decimal' : undefined\"\n :invalid=\"tried && !fieldOk(value)\"\n @keydown.enter.prevent=\"apply\"\n />\n <template v-if=\"needsTo\">\n <span class=\"dou-sheet-format__and\">{{ m.and }}</span>\n <DouInput\n v-model=\"to\"\n :aria-label=\"m.value\"\n :inputmode=\"numeric ? 'decimal' : undefined\"\n :invalid=\"tried && !fieldOk(to)\"\n @keydown.enter.prevent=\"apply\"\n />\n </template>\n </div>\n </DouFormItem>\n </template>\n <DouFormItem :label=\"m.prompt\" :help=\"m.promptHelp\">\n <DouInput v-model=\"prompt\" />\n </DouFormItem>\n <DouFormItem :label=\"m.message\" :help=\"m.messageHelp\">\n <DouInput v-model=\"message\" />\n </DouFormItem>\n <DouFormItem :help=\"m.strictHelp\">\n <DouCheckbox v-model=\"strict\">{{ m.strict }}</DouCheckbox>\n </DouFormItem>\n </DouForm>\n <template #footer=\"{ close }\">\n <DouButton\n v-if=\"editing\"\n variant=\"ghost\"\n tone=\"danger\"\n class=\"dou-sheet-validation__remove\"\n @click=\"remove\"\n >{{ m.remove }}</DouButton\n >\n <DouButton variant=\"outline\" @click=\"close\">{{ m.cancel }}</DouButton>\n <DouButton variant=\"solid\" @click=\"apply\">{{ m.apply }}</DouButton>\n </template>\n </DouDialog>\n</template>\n"],"mappings":"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"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { inject } from "vue";
|
|
2
|
+
// src/context.ts
|
|
3
|
+
var sheetContextKey = Symbol("dou-sheet");
|
|
4
|
+
/** The surrounding sheet; for overlays, cell types' components and the grid's slots. */
|
|
5
|
+
function useSheet() {
|
|
6
|
+
const context = inject(sheetContextKey, null);
|
|
7
|
+
if (!context) throw new Error("[@dou-ui/sheet] useSheet() must be called inside <DouSheet>");
|
|
8
|
+
return context;
|
|
9
|
+
}
|
|
10
|
+
export { sheetContextKey, useSheet };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import type { SheetFunction } from './formula/functions'\nimport { inject, type ComputedRef, type InjectionKey, type Ref } from 'vue'\nimport type { SheetBounds, SheetPoint } from './core/address'\nimport type { SheetResolvedType } from './core/cell-type'\nimport type { SheetData, SheetSortOrder, SheetStyle, SheetValue, SheetWorkbook } from './core/model'\nimport type { SheetResult } from './formula/values'\nimport type { SheetExporterInfo, SheetImporterInfo } from './core/file'\nimport type { SheetSelection } from './core/selection'\nimport type { SheetStylePatch } from './core/transaction'\nimport type { SheetMessages } from './locale'\nimport type { SheetExpose, SheetToolbarItem } from './types'\n\n/** A box in the grid, in px from its top left corner, as drawn now (after scrolling). */\nexport interface SheetRect {\n x: number\n y: number\n width: number\n height: number\n}\n\n/** Where a range shows: its part in view, with the edges the view cuts off. */\nexport interface SheetRangeRect extends SheetRect {\n cut: { top: boolean; right: boolean; bottom: boolean; left: boolean }\n}\n\n/** The surrounding sheet, as `useSheet()` and extensions see it. */\nexport interface SheetContext {\n /** The workbook, as of the last change. */\n doc: Readonly<Ref<SheetWorkbook>>\n /** The index of the sheet shown. */\n sheetIndex: ComputedRef<number>\n /** The sheet shown. */\n sheet: ComputedRef<SheetData>\n selection: Readonly<Ref<SheetSelection>>\n /** The cell the keyboard is on. */\n active: ComputedRef<SheetPoint>\n readonly: ComputedRef<boolean>\n /** Whether the grid or its cell editor has the keyboard focus. */\n focused: Readonly<Ref<boolean>>\n messages: ComputedRef<SheetMessages>\n /**\n * Calls `callback` for each selected cell of the sheet shown, once each,\n * row by row; a merged cell counts once, at its top left cell.\n */\n forEachSelected: (callback: (point: SheetPoint) => void) => void\n /** The value in a cell of the sheet shown; for a formula, the formula. */\n value: (point: SheetPoint) => SheetValue\n /** What a cell of the sheet shown comes to: its formula's result, or its value. */\n result: (point: SheetPoint) => SheetResult\n /** A cell's type and its settings, or `undefined` for a plain cell. */\n cellType: (point: SheetPoint) => SheetResolvedType | undefined\n /** Where a cell (or the merged cell it is in) is drawn now; `null` while it is out of view. */\n cellRect: (point: SheetPoint) => SheetRect | null\n /**\n * Where the part of a range of the sheet shown that is in view is drawn\n * now, past the frozen rows and columns too; `null` while none of it is.\n */\n rangeRect: (bounds: SheetBounds) => SheetRangeRect | null\n /**\n * Makes a change as the person using the grid, like the toolbar does.\n * Unlike the component's `transact`, a `readonly` grid refuses it:\n * the transaction comes back with `tr.cancelled` set (and no\n * `transactionCancel`), unless `meta.history` is `false`. Otherwise as\n * the component's: returns the transaction, `tr.changed` says whether\n * it changed anything, and protected cells refuse it unless\n * `meta.protection` or `meta.history` is `false`.\n */\n transact: SheetExpose['transact']\n /** Undoes as the person using the grid: does nothing on a `readonly` grid. */\n undo: SheetExpose['undo']\n /** Redoes as the person using the grid: does nothing on a `readonly` grid. */\n redo: SheetExpose['redo']\n canUndo: Readonly<Ref<boolean>>\n canRedo: Readonly<Ref<boolean>>\n select: SheetExpose['select']\n scrollTo: SheetExpose['scrollTo']\n edit: SheetExpose['edit']\n focus: SheetExpose['focus']\n showSheet: SheetExpose['showSheet']\n toCSV: SheetExpose['toCSV']\n exportSVG: SheetExpose['exportSVG']\n exportPNG: SheetExpose['exportPNG']\n print: SheetExpose['print']\n /** How a cell of the sheet shown looks: its style, or `{}`. A merged cell has its top left cell's. */\n styleAt: (point: SheetPoint) => SheetStyle\n /** A cell's number or date format. */\n formatAt: (point: SheetPoint) => string | undefined\n /**\n * Changes how the selected cells look, as `tr.styleCells` does; `null`\n * takes their styles off. Returns whether anything changed.\n */\n styleSelection: (patch: SheetStylePatch | null) => boolean\n /** Sets the format of the selected cells, or changes each with a function, as `tr.formatCells` does. */\n formatSelection: (\n format:\n string | undefined | ((format: string | undefined, value: SheetValue) => string | undefined),\n ) => boolean\n /** Takes the styles and formats off the selected cells. */\n clearFormatting: () => boolean\n /** Whether the selection touches merged cells. */\n merged: ComputedRef<boolean>\n /** Whether the selection can be merged: one range of more than one cell, not one merge already. */\n canMerge: ComputedRef<boolean>\n /** Merges the selection into one cell, telling how many values that cleared. */\n merge: () => void\n /** Splits the merged cells the selection touches. */\n unmerge: () => void\n /**\n * Sorts by the active cell's column: the selected rows, or the filter's\n * rows, or the block of cells around it. Returns whether it sorted.\n */\n sort: (order: SheetSortOrder) => boolean\n /** Whether the sheet shown has a filter. */\n filtered: ComputedRef<boolean>\n /** Puts a filter on the selection (or the block around the active cell), or takes it off. */\n toggleFilter: () => void\n /** Says `text` to screen readers. */\n announce: (text: string) => void\n /** What the sheet can do by name, built in and added by extensions: run them, or read their state. */\n commands: SheetExpose['commands']\n exportFile: SheetExpose['exportFile']\n saveFile: SheetExpose['saveFile']\n importFile: SheetExpose['importFile']\n /** The exporters, labels in the sheet's language: the built-in ones (CSV, PNG, SVG), then the extensions'. */\n exporters: ComputedRef<SheetExporterInfo[]>\n /** The importers, in the order they are asked: the extensions', then the built-in CSV one. */\n importers: ComputedRef<SheetImporterInfo[]>\n /** What a file picker for the importers accepts, such as `.csv,text/csv`. */\n importAccept: ComputedRef<string>\n /** The items extensions add to the toolbar, in priority order. */\n toolbarItems: ComputedRef<SheetToolbarItem[]>\n /** The cell being edited, for inputs outside the grid such as the formula bar. */\n editor: SheetEditorContext\n}\n\n/** How an input outside the grid edits the cell, for `editor.attach`. */\nexport interface SheetEditInputOptions {\n /**\n * The input shows the text and caret itself, following `editor.text`\n * and `editor.caret`, and reports its own with `input` and `moveCaret`;\n * the sheet doesn't write its value. For an input whose element isn't\n * what holds the text, such as a code editor's.\n */\n managed?: boolean\n /** What the function list and argument hints go under; the input by default. */\n anchor?: HTMLElement\n}\n\n/** Editing the active cell from outside the grid, as the formula bar does. */\nexport interface SheetEditorContext {\n /** The cell being edited and how: `'enter'` began by typing, so the arrows move on (or point, in a formula). */\n cell: ComputedRef<{ sheet: number; row: number; col: number; mode: 'enter' | 'edit' } | null>\n /** The text being edited. */\n text: Readonly<Ref<string>>\n /** Where the caret is in `text`. */\n caret: Readonly<Ref<number>>\n /** The text a cell edits as: its formula, or its value as typed. */\n textAt: (point: SheetPoint) => string\n /** Sets the text being edited, starting an edit of the active cell when none is open. */\n input: (text: string, caret?: number) => boolean\n /** Tells where the input's caret is, after keys or a click moved it. */\n moveCaret: (caret: number) => void\n /** Handles a key the way the cell's editor does (completion, pointing, Enter, Tab, Escape); `true` when it did. */\n key: (event: KeyboardEvent) => boolean\n /** Saves the edit, then moves the way Enter (`'down'`) or Tab (`'right'`) do. */\n commit: (move?: 'up' | 'down' | 'left' | 'right') => void\n /** Drops the edit. */\n cancel: () => void\n /** Lets an input edit the cell: focus moving to it keeps the edit open. Returns a function that undoes it. */\n attach: (\n el: HTMLInputElement | HTMLTextAreaElement,\n options?: SheetEditInputOptions,\n ) => () => void\n /** The id of the list of functions and argument hints, for `aria-controls`. */\n helpId: string\n /** The functions formulas can call, built in and added, by name. */\n functions: ComputedRef<readonly SheetFunction[]>\n}\n\nexport const sheetContextKey: InjectionKey<SheetContext> = Symbol('dou-sheet')\n\n/** Where a range shows: its part in view, with the edges the view cuts off. */\nexport interface SheetRangeRect extends SheetRect {\n cut: { top: boolean; right: boolean; bottom: boolean; left: boolean }\n}\n\n/** The surrounding sheet; for overlays, cell types' components and the grid's slots. */\nexport function useSheet() {\n const context = inject(sheetContextKey, null)\n if (!context) throw new Error('[@dou-ui/sheet] useSheet() must be called inside <DouSheet>')\n return context\n}\n"],"mappings":";;AAmLA,IAAa,kBAA8C,OAAO,WAAW;;AAQ7E,SAAgB,WAAW;CACzB,MAAM,UAAU,OAAO,iBAAiB,IAAI;CAC5C,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,6DAA6D;CAC3F,OAAO;AACT"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// src/core/address.ts
|
|
2
|
+
/** A column's letters: 0 is `A`, 25 is `Z`, 26 is `AA`. */
|
|
3
|
+
function columnName(col) {
|
|
4
|
+
let name = "";
|
|
5
|
+
for (let n = col + 1; n > 0; n = Math.floor((n - 1) / 26)) name = String.fromCharCode(65 + (n - 1) % 26) + name;
|
|
6
|
+
return name;
|
|
7
|
+
}
|
|
8
|
+
/** A column's number from its letters, any case; `-1` when they aren't letters. */
|
|
9
|
+
function columnIndex(name) {
|
|
10
|
+
if (!/^[a-z]+$/i.test(name)) return -1;
|
|
11
|
+
let col = 0;
|
|
12
|
+
for (const char of name.toUpperCase()) col = col * 26 + char.charCodeAt(0) - 64;
|
|
13
|
+
return col - 1;
|
|
14
|
+
}
|
|
15
|
+
var CELL = /^\$?([a-z]+)\$?([1-9]\d*)$/i;
|
|
16
|
+
/** `'B3'` as `{ row: 2, col: 1 }`; `$` marks are allowed. `null` when it isn't a cell name. */
|
|
17
|
+
function parseCell(name) {
|
|
18
|
+
const match = CELL.exec(name.trim());
|
|
19
|
+
if (!match) return null;
|
|
20
|
+
return {
|
|
21
|
+
row: Number(match[2]) - 1,
|
|
22
|
+
col: columnIndex(match[1])
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** A cell's name, such as `B3`. */
|
|
26
|
+
var formatCell = (point) => `${columnName(point.col)}${point.row + 1}`;
|
|
27
|
+
/**
|
|
28
|
+
* `'A1:C4'` or `'B2'` as a range; also whole columns (`'B:D'`) and whole
|
|
29
|
+
* rows (`'2:3'`), which run to `Infinity` until kept inside a sheet.
|
|
30
|
+
* `null` when it isn't one.
|
|
31
|
+
*/
|
|
32
|
+
function parseRange(text) {
|
|
33
|
+
const [from, to, extra] = text.trim().split(":");
|
|
34
|
+
if (extra != null || from == null) return null;
|
|
35
|
+
const start = parseCell(from);
|
|
36
|
+
if (start) {
|
|
37
|
+
const end = to == null ? start : parseCell(to);
|
|
38
|
+
return end ? {
|
|
39
|
+
start,
|
|
40
|
+
end
|
|
41
|
+
} : null;
|
|
42
|
+
}
|
|
43
|
+
if (to == null) return null;
|
|
44
|
+
const a = from.replaceAll("$", "");
|
|
45
|
+
const b = to.replaceAll("$", "");
|
|
46
|
+
if (/^[a-z]+$/i.test(a) && /^[a-z]+$/i.test(b)) return {
|
|
47
|
+
start: {
|
|
48
|
+
row: 0,
|
|
49
|
+
col: columnIndex(a)
|
|
50
|
+
},
|
|
51
|
+
end: {
|
|
52
|
+
row: Infinity,
|
|
53
|
+
col: columnIndex(b)
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
if (/^[1-9]\d*$/.test(a) && /^[1-9]\d*$/.test(b)) return {
|
|
57
|
+
start: {
|
|
58
|
+
row: Number(a) - 1,
|
|
59
|
+
col: 0
|
|
60
|
+
},
|
|
61
|
+
end: {
|
|
62
|
+
row: Number(b) - 1,
|
|
63
|
+
col: Infinity
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A range's name with its corners in order, such as `A1:C4`; one cell is
|
|
70
|
+
* just its name. Given the sheet's size, whole columns read `B:D` and
|
|
71
|
+
* whole rows `2:3`.
|
|
72
|
+
*/
|
|
73
|
+
function formatRange(range, size) {
|
|
74
|
+
const b = boundsOf(range);
|
|
75
|
+
const rows = size?.rows ?? Infinity;
|
|
76
|
+
const cols = size?.cols ?? Infinity;
|
|
77
|
+
const allRows = b.top === 0 && b.bottom >= rows - 1;
|
|
78
|
+
const allCols = b.left === 0 && b.right >= cols - 1;
|
|
79
|
+
if (allRows && !(allCols && size)) return `${columnName(b.left)}:${columnName(b.right)}`;
|
|
80
|
+
if (allCols && !allRows) return `${b.top + 1}:${b.bottom + 1}`;
|
|
81
|
+
const first = formatCell({
|
|
82
|
+
row: b.top,
|
|
83
|
+
col: b.left
|
|
84
|
+
});
|
|
85
|
+
return b.top === b.bottom && b.left === b.right ? first : `${first}:${formatCell({
|
|
86
|
+
row: b.bottom,
|
|
87
|
+
col: b.right
|
|
88
|
+
})}`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Splits a reference into the sheet it names and the rest: `'表 2'!A5`
|
|
92
|
+
* and `表2!A5` both give `表 2` / `表2` and `A5`. Without a `!`, no sheet.
|
|
93
|
+
*/
|
|
94
|
+
function splitSheet(text) {
|
|
95
|
+
const at = text.lastIndexOf("!");
|
|
96
|
+
if (at === -1) return { ref: text };
|
|
97
|
+
let sheet = text.slice(0, at);
|
|
98
|
+
if (sheet.length > 1 && sheet.startsWith("'") && sheet.endsWith("'")) sheet = sheet.slice(1, -1).replaceAll("''", "'");
|
|
99
|
+
return {
|
|
100
|
+
sheet,
|
|
101
|
+
ref: text.slice(at + 1)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function boundsOf(range) {
|
|
105
|
+
const { start, end } = range;
|
|
106
|
+
return {
|
|
107
|
+
top: Math.min(start.row, end.row),
|
|
108
|
+
left: Math.min(start.col, end.col),
|
|
109
|
+
bottom: Math.max(start.row, end.row),
|
|
110
|
+
right: Math.max(start.col, end.col)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
var inBounds = (b, row, col) => row >= b.top && row <= b.bottom && col >= b.left && col <= b.right;
|
|
114
|
+
/** A range of one cell. */
|
|
115
|
+
var pointRange = (point) => ({
|
|
116
|
+
start: point,
|
|
117
|
+
end: point
|
|
118
|
+
});
|
|
119
|
+
/**
|
|
120
|
+
* A reference: `A1`, `A1:C4`, `B:D`, `2:3`, maybe after a sheet
|
|
121
|
+
* (`表2!A1`, `'表 2'!A1`). Not part of a longer name (`LOG10(`, `A1B`),
|
|
122
|
+
* and quoted text is skipped whole.
|
|
123
|
+
*/
|
|
124
|
+
var REF = new RegExp(["\"(?:[^\"]|\"\")*\"", "(?<![\\p{L}\\p{N}_.$'!])(?:('(?:[^']|'')+'|[\\p{L}_][\\p{L}\\p{N}_.]*)!)?(?:(\\$?[a-z]{1,3}\\$?[1-9]\\d*)(?::(\\$?[a-z]{1,3}\\$?[1-9]\\d*))?|(\\$?[a-z]{1,3}):(\\$?[a-z]{1,3})|(\\$?[1-9]\\d*):(\\$?[1-9]\\d*))(?![\\p{L}\\p{N}_(!])"].join("|"), "giu");
|
|
125
|
+
function readEnd(text) {
|
|
126
|
+
const match = /^(\$?)([a-z]*)(\$?)(\d*)$/i.exec(text);
|
|
127
|
+
const end = {
|
|
128
|
+
colMark: false,
|
|
129
|
+
rowMark: false
|
|
130
|
+
};
|
|
131
|
+
if (match[2]) {
|
|
132
|
+
end.col = columnIndex(match[2]);
|
|
133
|
+
end.colMark = match[1] === "$";
|
|
134
|
+
if (match[4]) {
|
|
135
|
+
end.row = Number(match[4]) - 1;
|
|
136
|
+
end.rowMark = match[3] === "$";
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
end.row = Number(match[4]) - 1;
|
|
140
|
+
end.rowMark = match[1] === "$" || match[3] === "$";
|
|
141
|
+
}
|
|
142
|
+
return end;
|
|
143
|
+
}
|
|
144
|
+
function writeEnd(end) {
|
|
145
|
+
let text = "";
|
|
146
|
+
if (end.col != null) text += `${end.colMark ? "$" : ""}${columnName(end.col)}`;
|
|
147
|
+
if (end.row != null) text += `${end.rowMark ? "$" : ""}${end.row + 1}`;
|
|
148
|
+
return text;
|
|
149
|
+
}
|
|
150
|
+
/** A sheet's name as a reference writes it: quoted unless it is a plain word. */
|
|
151
|
+
function quoteSheet(name) {
|
|
152
|
+
return /^[\p{L}_][\p{L}\p{N}_.]*$/u.test(name) && !parseCell(name) && !/^[rc]\d*([rc]\d*)?$/i.test(name) ? name : `'${name.replaceAll("'", "''")}'`;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Calls `map` for every reference in a formula, with its sheet (as
|
|
156
|
+
* written, unquoted) and its two ends, and puts back the text it returns.
|
|
157
|
+
*/
|
|
158
|
+
function eachRef(formula, map) {
|
|
159
|
+
if (!formula.startsWith("=")) return formula;
|
|
160
|
+
return formula.replace(REF, (match, sheet, ...parts) => {
|
|
161
|
+
const found = parts.slice(0, 6).filter((part) => part != null);
|
|
162
|
+
if (!found.length) return match;
|
|
163
|
+
const at = sheet ? splitSheet(`${sheet}!`).sheet : void 0;
|
|
164
|
+
const a = readEnd(found[0]);
|
|
165
|
+
return map(at, a, found[1] ? readEnd(found[1]) : a, match);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function writeRef(sheet, a, b, single, written) {
|
|
169
|
+
const prefix = written ?? (sheet != null ? `${quoteSheet(sheet)}!` : "");
|
|
170
|
+
return single ? prefix + writeEnd(a) : `${prefix}${writeEnd(a)}:${writeEnd(b)}`;
|
|
171
|
+
}
|
|
172
|
+
/** One end of a reference moved by `rows` and `cols`, unless fixed; `null` past the first row or column. */
|
|
173
|
+
function shiftEnd(end, rows, cols) {
|
|
174
|
+
const next = { ...end };
|
|
175
|
+
if (next.col != null && !next.colMark) next.col += cols;
|
|
176
|
+
if (next.row != null && !next.rowMark) next.row += rows;
|
|
177
|
+
return (next.col ?? 0) < 0 || (next.row ?? 0) < 0 ? null : next;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A formula moved by `rows` and `cols`, as copying or filling it does:
|
|
181
|
+
* references without `$` move along, `$A$1` stays. A reference pushed past
|
|
182
|
+
* the first row or column becomes `#REF!`.
|
|
183
|
+
*/
|
|
184
|
+
function shiftFormula(formula, rows, cols) {
|
|
185
|
+
if (rows === 0 && cols === 0) return formula;
|
|
186
|
+
return eachRef(formula, (sheet, a, b, text) => {
|
|
187
|
+
const single = a === b;
|
|
188
|
+
const from = shiftEnd(a, rows, cols);
|
|
189
|
+
const to = single ? from : shiftEnd(b, rows, cols);
|
|
190
|
+
if (!from || !to) return text.includes("!") ? `${text.slice(0, text.lastIndexOf("!") + 1)}#REF!` : "#REF!";
|
|
191
|
+
return writeRef(sheet, from, to, single);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Rewrites the references in a formula on sheet `here` that point at cells
|
|
196
|
+
* on sheet `sheet`, by `map`: references to cells that moved follow them,
|
|
197
|
+
* references to cells that are gone become `#REF!`. Unlike copying, fixed
|
|
198
|
+
* references (`$A$1`) move too.
|
|
199
|
+
*/
|
|
200
|
+
function moveReferences(formula, here, sheet, map) {
|
|
201
|
+
return eachRef(formula, (named, a, b, text) => {
|
|
202
|
+
if ((named ?? here) !== sheet) return text;
|
|
203
|
+
const single = a === b;
|
|
204
|
+
const bounds = {
|
|
205
|
+
top: Math.min(a.row ?? 0, b.row ?? 0),
|
|
206
|
+
left: Math.min(a.col ?? 0, b.col ?? 0),
|
|
207
|
+
bottom: a.row == null ? Infinity : Math.max(a.row, b.row),
|
|
208
|
+
right: a.col == null ? Infinity : Math.max(a.col, b.col)
|
|
209
|
+
};
|
|
210
|
+
const result = map(bounds);
|
|
211
|
+
const prefix = text.includes("!") ? text.slice(0, text.lastIndexOf("!") + 1) : "";
|
|
212
|
+
if (!result) return `${prefix}#REF!`;
|
|
213
|
+
const next = "bounds" in result ? result.bounds : result;
|
|
214
|
+
const to = "bounds" in result ? result.sheet : named ?? here;
|
|
215
|
+
if (to === (named ?? here) && next.top === bounds.top && next.left === bounds.left && next.bottom === bounds.bottom && next.right === bounds.right) return text;
|
|
216
|
+
const out = to === here && named == null ? void 0 : to;
|
|
217
|
+
const keep = named != null && to === named ? prefix : void 0;
|
|
218
|
+
const first = (a.row ?? Infinity) <= (b.row ?? Infinity);
|
|
219
|
+
const left = (a.col ?? Infinity) <= (b.col ?? Infinity);
|
|
220
|
+
const end = (base, top, l) => ({
|
|
221
|
+
...base,
|
|
222
|
+
col: base.col == null ? void 0 : l ? next.left : next.right,
|
|
223
|
+
row: base.row == null ? void 0 : top ? next.top : next.bottom
|
|
224
|
+
});
|
|
225
|
+
return writeRef(out, end(a, first, left), end(b, !first, !left), single, keep);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* A formula with its references to sheet `from` naming sheet `to`
|
|
230
|
+
* instead, as renaming a sheet does. References without a sheet stay as
|
|
231
|
+
* they are, also in a formula on the renamed sheet itself.
|
|
232
|
+
*/
|
|
233
|
+
function renameReferences(formula, from, to) {
|
|
234
|
+
if (from === to) return formula;
|
|
235
|
+
return eachRef(formula, (named, a, b, text) => named === from ? writeRef(to, a, b, a === b) : text);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* A formula with references to several sheets renamed at once, by old
|
|
239
|
+
* name: `{ 预算: '预算 (2)' }`. Names that swap or chain are each renamed
|
|
240
|
+
* once. A name mapped to itself has its references written again, quoted
|
|
241
|
+
* as `quoteSheet` quotes it.
|
|
242
|
+
*/
|
|
243
|
+
function renameReferencesAll(formula, names) {
|
|
244
|
+
if (!names.size) return formula;
|
|
245
|
+
return eachRef(formula, (named, a, b, text) => {
|
|
246
|
+
const to = named == null ? void 0 : names.get(named);
|
|
247
|
+
return to != null ? writeRef(to, a, b, a === b) : text;
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/** A formula with its references to sheet `sheet`, which is gone, reading `#REF!`. */
|
|
251
|
+
function dropReferences(formula, sheet) {
|
|
252
|
+
return eachRef(formula, (named, _a, _b, text) => named === sheet ? "#REF!" : text);
|
|
253
|
+
}
|
|
254
|
+
export { boundsOf, columnIndex, columnName, dropReferences, eachRef, formatCell, formatRange, inBounds, moveReferences, parseCell, parseRange, pointRange, quoteSheet, renameReferences, renameReferencesAll, shiftFormula, splitSheet, writeRef };
|
|
255
|
+
|
|
256
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","names":[],"sources":["../../src/core/address.ts"],"sourcesContent":["/*\n * Cells are addressed by zero-based row and column numbers in code, and\n * by \"A1\" names wherever people read or write them.\n */\n\n/** A cell, by zero-based row and column. */\nexport interface SheetPoint {\n row: number\n col: number\n}\n\n/**\n * A rectangle of cells between two corners. `start` is where the range was\n * started (the anchor), so it may be below or right of `end`.\n */\nexport interface SheetRange {\n start: SheetPoint\n end: SheetPoint\n}\n\n/** A range with its edges in order: `top <= bottom`, `left <= right`. */\nexport interface SheetBounds {\n top: number\n left: number\n bottom: number\n right: number\n}\n\n/** A column's letters: 0 is `A`, 25 is `Z`, 26 is `AA`. */\nexport function columnName(col: number) {\n let name = ''\n for (let n = col + 1; n > 0; n = Math.floor((n - 1) / 26))\n name = String.fromCharCode(65 + ((n - 1) % 26)) + name\n return name\n}\n\n/** A column's number from its letters, any case; `-1` when they aren't letters. */\nexport function columnIndex(name: string) {\n if (!/^[a-z]+$/i.test(name)) return -1\n let col = 0\n for (const char of name.toUpperCase()) col = col * 26 + char.charCodeAt(0) - 64\n return col - 1\n}\n\nconst CELL = /^\\$?([a-z]+)\\$?([1-9]\\d*)$/i\n\n/** `'B3'` as `{ row: 2, col: 1 }`; `$` marks are allowed. `null` when it isn't a cell name. */\nexport function parseCell(name: string): SheetPoint | null {\n const match = CELL.exec(name.trim())\n if (!match) return null\n return { row: Number(match[2]) - 1, col: columnIndex(match[1]!) }\n}\n\n/** A cell's name, such as `B3`. */\nexport const formatCell = (point: SheetPoint) => `${columnName(point.col)}${point.row + 1}`\n\n/** A cell, as a name such as `'B3'` or as a point. */\nexport type SheetCellTarget = string | SheetPoint\n\n/**\n * `'A1:C4'` or `'B2'` as a range; also whole columns (`'B:D'`) and whole\n * rows (`'2:3'`), which run to `Infinity` until kept inside a sheet.\n * `null` when it isn't one.\n */\nexport function parseRange(text: string): SheetRange | null {\n const [from, to, extra] = text.trim().split(':')\n if (extra != null || from == null) return null\n const start = parseCell(from)\n if (start) {\n const end = to == null ? start : parseCell(to)\n return end ? { start, end } : null\n }\n if (to == null) return null\n const a = from.replaceAll('$', '')\n const b = to.replaceAll('$', '')\n if (/^[a-z]+$/i.test(a) && /^[a-z]+$/i.test(b))\n return {\n start: { row: 0, col: columnIndex(a) },\n end: { row: Infinity, col: columnIndex(b) },\n }\n if (/^[1-9]\\d*$/.test(a) && /^[1-9]\\d*$/.test(b))\n return { start: { row: Number(a) - 1, col: 0 }, end: { row: Number(b) - 1, col: Infinity } }\n return null\n}\n\n/**\n * A range's name with its corners in order, such as `A1:C4`; one cell is\n * just its name. Given the sheet's size, whole columns read `B:D` and\n * whole rows `2:3`.\n */\nexport function formatRange(range: SheetRange, size?: { rows: number; cols: number }) {\n const b = boundsOf(range)\n const rows = size?.rows ?? Infinity\n const cols = size?.cols ?? Infinity\n const allRows = b.top === 0 && b.bottom >= rows - 1\n const allCols = b.left === 0 && b.right >= cols - 1\n if (allRows && !(allCols && size)) return `${columnName(b.left)}:${columnName(b.right)}`\n if (allCols && !allRows) return `${b.top + 1}:${b.bottom + 1}`\n const first = formatCell({ row: b.top, col: b.left })\n return b.top === b.bottom && b.left === b.right\n ? first\n : `${first}:${formatCell({ row: b.bottom, col: b.right })}`\n}\n\n/**\n * Splits a reference into the sheet it names and the rest: `'表 2'!A5`\n * and `表2!A5` both give `表 2` / `表2` and `A5`. Without a `!`, no sheet.\n */\nexport function splitSheet(text: string): { sheet?: string; ref: string } {\n const at = text.lastIndexOf('!')\n if (at === -1) return { ref: text }\n let sheet = text.slice(0, at)\n if (sheet.length > 1 && sheet.startsWith(\"'\") && sheet.endsWith(\"'\"))\n sheet = sheet.slice(1, -1).replaceAll(\"''\", \"'\")\n return { sheet, ref: text.slice(at + 1) }\n}\n\nexport function boundsOf(range: SheetRange): SheetBounds {\n const { start, end } = range\n return {\n top: Math.min(start.row, end.row),\n left: Math.min(start.col, end.col),\n bottom: Math.max(start.row, end.row),\n right: Math.max(start.col, end.col),\n }\n}\n\nexport const inBounds = (b: SheetBounds, row: number, col: number) =>\n row >= b.top && row <= b.bottom && col >= b.left && col <= b.right\n\n/** A range of one cell. */\nexport const pointRange = (point: SheetPoint): SheetRange => ({ start: point, end: point })\n\n/*\n * References inside formulas. Formulas are kept as text, so moving cells\n * around rewrites the references in them, the way copying, inserting and\n * deleting do in other spreadsheet programs.\n */\n\n/** One end of a reference: a column, a row or both, each maybe fixed with `$`. */\nexport interface RefEnd {\n col?: number\n row?: number\n colMark: boolean\n rowMark: boolean\n}\n\n/**\n * A reference: `A1`, `A1:C4`, `B:D`, `2:3`, maybe after a sheet\n * (`表2!A1`, `'表 2'!A1`). Not part of a longer name (`LOG10(`, `A1B`),\n * and quoted text is skipped whole.\n */\nconst REF = new RegExp(\n [\n '\"(?:[^\"]|\"\")*\"',\n \"(?<![\\\\p{L}\\\\p{N}_.$'!])\" +\n \"(?:('(?:[^']|'')+'|[\\\\p{L}_][\\\\p{L}\\\\p{N}_.]*)!)?\" +\n '(?:(\\\\$?[a-z]{1,3}\\\\$?[1-9]\\\\d*)(?::(\\\\$?[a-z]{1,3}\\\\$?[1-9]\\\\d*))?' +\n '|(\\\\$?[a-z]{1,3}):(\\\\$?[a-z]{1,3})' +\n '|(\\\\$?[1-9]\\\\d*):(\\\\$?[1-9]\\\\d*))' +\n '(?![\\\\p{L}\\\\p{N}_(!])',\n ].join('|'),\n 'giu',\n)\n\nfunction readEnd(text: string): RefEnd {\n const match = /^(\\$?)([a-z]*)(\\$?)(\\d*)$/i.exec(text)!\n const end: RefEnd = { colMark: false, rowMark: false }\n if (match[2]) {\n end.col = columnIndex(match[2])\n end.colMark = match[1] === '$'\n if (match[4]) {\n end.row = Number(match[4]) - 1\n end.rowMark = match[3] === '$'\n }\n } else {\n end.row = Number(match[4]) - 1\n end.rowMark = match[1] === '$' || match[3] === '$'\n }\n return end\n}\n\nfunction writeEnd(end: RefEnd) {\n let text = ''\n if (end.col != null) text += `${end.colMark ? '$' : ''}${columnName(end.col)}`\n if (end.row != null) text += `${end.rowMark ? '$' : ''}${end.row + 1}`\n return text\n}\n\n/** A sheet's name as a reference writes it: quoted unless it is a plain word. */\nexport function quoteSheet(name: string) {\n // names that read as a cell, `AB12` or `R1C1`, are quoted too\n return /^[\\p{L}_][\\p{L}\\p{N}_.]*$/u.test(name) &&\n !parseCell(name) &&\n !/^[rc]\\d*([rc]\\d*)?$/i.test(name)\n ? name\n : `'${name.replaceAll(\"'\", \"''\")}'`\n}\n\n/**\n * Calls `map` for every reference in a formula, with its sheet (as\n * written, unquoted) and its two ends, and puts back the text it returns.\n */\nexport function eachRef(\n formula: string,\n map: (sheet: string | undefined, a: RefEnd, b: RefEnd, text: string) => string,\n) {\n if (!formula.startsWith('=')) return formula\n return formula.replace(REF, (match, sheet?: string, ...parts: (string | undefined)[]) => {\n const found = parts.slice(0, 6).filter((part) => part != null)\n if (!found.length) return match\n const at = sheet ? splitSheet(`${sheet}!`).sheet : undefined\n const a = readEnd(found[0]!)\n const b = found[1] ? readEnd(found[1]) : a\n return map(at, a, b, match)\n })\n}\n\nexport function writeRef(\n sheet: string | undefined,\n a: RefEnd,\n b: RefEnd,\n single: boolean,\n written?: string,\n) {\n const prefix = written ?? (sheet != null ? `${quoteSheet(sheet)}!` : '')\n return single ? prefix + writeEnd(a) : `${prefix}${writeEnd(a)}:${writeEnd(b)}`\n}\n\n/** One end of a reference moved by `rows` and `cols`, unless fixed; `null` past the first row or column. */\nfunction shiftEnd(end: RefEnd, rows: number, cols: number): RefEnd | null {\n const next = { ...end }\n if (next.col != null && !next.colMark) next.col += cols\n if (next.row != null && !next.rowMark) next.row += rows\n return (next.col ?? 0) < 0 || (next.row ?? 0) < 0 ? null : next\n}\n\n/**\n * A formula moved by `rows` and `cols`, as copying or filling it does:\n * references without `$` move along, `$A$1` stays. A reference pushed past\n * the first row or column becomes `#REF!`.\n */\nexport function shiftFormula(formula: string, rows: number, cols: number) {\n if (rows === 0 && cols === 0) return formula\n return eachRef(formula, (sheet, a, b, text) => {\n const single = a === b\n const from = shiftEnd(a, rows, cols)\n const to = single ? from : shiftEnd(b, rows, cols)\n if (!from || !to)\n return text.includes('!') ? `${text.slice(0, text.lastIndexOf('!') + 1)}#REF!` : '#REF!'\n return writeRef(sheet, from, to, single)\n })\n}\n\n/**\n * Where the cells of a range are after a change to a sheet: the same\n * bounds, new bounds, bounds on another sheet, or `null` when they are\n * gone. Whole columns run from row 0 to `Infinity`, whole rows likewise.\n */\nexport type SheetRefMap = (\n bounds: SheetBounds,\n) => SheetBounds | { sheet: string; bounds: SheetBounds } | null\n\n/**\n * Rewrites the references in a formula on sheet `here` that point at cells\n * on sheet `sheet`, by `map`: references to cells that moved follow them,\n * references to cells that are gone become `#REF!`. Unlike copying, fixed\n * references (`$A$1`) move too.\n */\nexport function moveReferences(formula: string, here: string, sheet: string, map: SheetRefMap) {\n return eachRef(formula, (named, a, b, text) => {\n if ((named ?? here) !== sheet) return text\n const single = a === b\n const bounds: SheetBounds = {\n top: Math.min(a.row ?? 0, b.row ?? 0),\n left: Math.min(a.col ?? 0, b.col ?? 0),\n bottom: a.row == null ? Infinity : Math.max(a.row, b.row!),\n right: a.col == null ? Infinity : Math.max(a.col, b.col!),\n }\n const result = map(bounds)\n const prefix = text.includes('!') ? text.slice(0, text.lastIndexOf('!') + 1) : ''\n if (!result) return `${prefix}#REF!`\n const next = 'bounds' in result ? result.bounds : result\n const to = 'bounds' in result ? result.sheet : (named ?? here)\n const same =\n to === (named ?? here) &&\n next.top === bounds.top &&\n next.left === bounds.left &&\n next.bottom === bounds.bottom &&\n next.right === bounds.right\n if (same) return text\n // a reference that now points at another sheet names it; one that named its sheet keeps how\n const out = to === here && named == null ? undefined : to\n const keep = named != null && to === named ? prefix : undefined\n const first = (a.row ?? Infinity) <= (b.row ?? Infinity)\n const left = (a.col ?? Infinity) <= (b.col ?? Infinity)\n const end = (base: RefEnd, top: boolean, l: boolean): RefEnd => ({\n ...base,\n col: base.col == null ? undefined : l ? next.left : next.right,\n row: base.row == null ? undefined : top ? next.top : next.bottom,\n })\n return writeRef(out, end(a, first, left), end(b, !first, !left), single, keep)\n })\n}\n\n/**\n * A formula with its references to sheet `from` naming sheet `to`\n * instead, as renaming a sheet does. References without a sheet stay as\n * they are, also in a formula on the renamed sheet itself.\n */\nexport function renameReferences(formula: string, from: string, to: string) {\n if (from === to) return formula\n return eachRef(formula, (named, a, b, text) =>\n named === from ? writeRef(to, a, b, a === b) : text,\n )\n}\n\n/**\n * A formula with references to several sheets renamed at once, by old\n * name: `{ 预算: '预算 (2)' }`. Names that swap or chain are each renamed\n * once. A name mapped to itself has its references written again, quoted\n * as `quoteSheet` quotes it.\n */\nexport function renameReferencesAll(formula: string, names: ReadonlyMap<string, string>) {\n if (!names.size) return formula\n return eachRef(formula, (named, a, b, text) => {\n const to = named == null ? undefined : names.get(named)\n return to != null ? writeRef(to, a, b, a === b) : text\n })\n}\n\n/** A formula with its references to sheet `sheet`, which is gone, reading `#REF!`. */\nexport function dropReferences(formula: string, sheet: string) {\n return eachRef(formula, (named, _a, _b, text) => (named === sheet ? '#REF!' : text))\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/core/axis.ts
|
|
2
|
+
/**
|
|
3
|
+
* Where each row (or column) starts, for a list of rows that share one
|
|
4
|
+
* size except for a few. Offsets are summed once, so finding a row's place
|
|
5
|
+
* and the row at a place are a lookup and a binary search.
|
|
6
|
+
*/
|
|
7
|
+
var SheetAxis = class {
|
|
8
|
+
count;
|
|
9
|
+
base;
|
|
10
|
+
sizes;
|
|
11
|
+
/** `offsets[i]` is where item `i` starts; the last entry is the total. */
|
|
12
|
+
offsets;
|
|
13
|
+
constructor(count, base, sizes = {}) {
|
|
14
|
+
this.count = count;
|
|
15
|
+
this.base = base;
|
|
16
|
+
this.sizes = sizes;
|
|
17
|
+
const offsets = new Float64Array(count + 1);
|
|
18
|
+
let changed = false;
|
|
19
|
+
for (const key in sizes) if (Number(key) < count) {
|
|
20
|
+
changed = true;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
if (!changed) for (let i = 0; i <= count; i++) offsets[i] = i * base;
|
|
24
|
+
else {
|
|
25
|
+
let at = 0;
|
|
26
|
+
for (let i = 0; i < count; i++) {
|
|
27
|
+
offsets[i] = at;
|
|
28
|
+
at += sizes[i] ?? base;
|
|
29
|
+
}
|
|
30
|
+
offsets[count] = at;
|
|
31
|
+
}
|
|
32
|
+
this.offsets = offsets;
|
|
33
|
+
}
|
|
34
|
+
get total() {
|
|
35
|
+
return this.offsets[this.count];
|
|
36
|
+
}
|
|
37
|
+
/** Where item `index` starts; past the end, the total. */
|
|
38
|
+
offset(index) {
|
|
39
|
+
return this.offsets[Math.max(0, Math.min(this.count, index))];
|
|
40
|
+
}
|
|
41
|
+
size(index) {
|
|
42
|
+
return this.offset(index + 1) - this.offset(index);
|
|
43
|
+
}
|
|
44
|
+
/** Whether item `index` is hidden (its size is 0). */
|
|
45
|
+
hidden(index) {
|
|
46
|
+
return this.size(index) === 0;
|
|
47
|
+
}
|
|
48
|
+
/** The item at `px`, clamped to the first and last; hidden items are skipped. */
|
|
49
|
+
indexAt(px) {
|
|
50
|
+
const { offsets, count } = this;
|
|
51
|
+
if (count === 0) return 0;
|
|
52
|
+
if (px <= 0) return this.visibleFrom(0, 1);
|
|
53
|
+
if (px >= this.total) return this.visibleFrom(count - 1, -1);
|
|
54
|
+
let low = 0;
|
|
55
|
+
let high = count - 1;
|
|
56
|
+
while (low < high) {
|
|
57
|
+
const mid = low + high + 1 >> 1;
|
|
58
|
+
if (offsets[mid] <= px) low = mid;
|
|
59
|
+
else high = mid - 1;
|
|
60
|
+
}
|
|
61
|
+
return this.visibleFrom(low, -1);
|
|
62
|
+
}
|
|
63
|
+
/** The first item from `index` on (going by `step`) that is not hidden; `index` when all are. */
|
|
64
|
+
visibleFrom(index, step) {
|
|
65
|
+
for (let i = index; i >= 0 && i < this.count; i += step) if (!this.hidden(i)) return i;
|
|
66
|
+
for (let i = index; i >= 0 && i < this.count; i -= step) if (!this.hidden(i)) return i;
|
|
67
|
+
return index;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
export { SheetAxis };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=axis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axis.js","names":[],"sources":["../../src/core/axis.ts"],"sourcesContent":["/**\n * Where each row (or column) starts, for a list of rows that share one\n * size except for a few. Offsets are summed once, so finding a row's place\n * and the row at a place are a lookup and a binary search.\n */\nexport class SheetAxis {\n /** `offsets[i]` is where item `i` starts; the last entry is the total. */\n private offsets: Float64Array\n\n constructor(\n readonly count: number,\n readonly base: number,\n readonly sizes: Readonly<Record<number, number>> = {},\n ) {\n const offsets = new Float64Array(count + 1)\n let changed = false\n for (const key in sizes) {\n if (Number(key) < count) {\n changed = true\n break\n }\n }\n if (!changed) {\n for (let i = 0; i <= count; i++) offsets[i] = i * base\n } else {\n let at = 0\n for (let i = 0; i < count; i++) {\n offsets[i] = at\n at += sizes[i] ?? base\n }\n offsets[count] = at\n }\n this.offsets = offsets\n }\n\n get total() {\n return this.offsets[this.count]!\n }\n\n /** Where item `index` starts; past the end, the total. */\n offset(index: number) {\n return this.offsets[Math.max(0, Math.min(this.count, index))]!\n }\n\n size(index: number) {\n return this.offset(index + 1) - this.offset(index)\n }\n\n /** Whether item `index` is hidden (its size is 0). */\n hidden(index: number) {\n return this.size(index) === 0\n }\n\n /** The item at `px`, clamped to the first and last; hidden items are skipped. */\n indexAt(px: number) {\n const { offsets, count } = this\n if (count === 0) return 0\n if (px <= 0) return this.visibleFrom(0, 1)\n if (px >= this.total) return this.visibleFrom(count - 1, -1)\n let low = 0\n let high = count - 1\n // the last item that starts at or before px\n while (low < high) {\n const mid = (low + high + 1) >> 1\n if (offsets[mid]! <= px) low = mid\n else high = mid - 1\n }\n return this.visibleFrom(low, -1)\n }\n\n /** The first item from `index` on (going by `step`) that is not hidden; `index` when all are. */\n visibleFrom(index: number, step: 1 | -1) {\n for (let i = index; i >= 0 && i < this.count; i += step) if (!this.hidden(i)) return i\n for (let i = index; i >= 0 && i < this.count; i -= step) if (!this.hidden(i)) return i\n return index\n }\n}\n"],"mappings":";;;;;;AAKA,IAAa,YAAb,MAAuB;CAKV;CACA;CACA;;CALX;CAEA,YACE,OACA,MACA,QAAmD,CAAC,GACpD;EAHS,KAAA,QAAA;EACA,KAAA,OAAA;EACA,KAAA,QAAA;EAET,MAAM,UAAU,IAAI,aAAa,QAAQ,CAAC;EAC1C,IAAI,UAAU;EACd,KAAK,MAAM,OAAO,OAChB,IAAI,OAAO,GAAG,IAAI,OAAO;GACvB,UAAU;GACV;EACF;EAEF,IAAI,CAAC,SACH,KAAK,IAAI,IAAI,GAAG,KAAK,OAAO,KAAK,QAAQ,KAAK,IAAI;OAC7C;GACL,IAAI,KAAK;GACT,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;IAC9B,QAAQ,KAAK;IACb,MAAM,MAAM,MAAM;GACpB;GACA,QAAQ,SAAS;EACnB;EACA,KAAK,UAAU;CACjB;CAEA,IAAI,QAAQ;EACV,OAAO,KAAK,QAAQ,KAAK;CAC3B;;CAGA,OAAO,OAAe;EACpB,OAAO,KAAK,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,KAAK,CAAC;CAC7D;CAEA,KAAK,OAAe;EAClB,OAAO,KAAK,OAAO,QAAQ,CAAC,IAAI,KAAK,OAAO,KAAK;CACnD;;CAGA,OAAO,OAAe;EACpB,OAAO,KAAK,KAAK,KAAK,MAAM;CAC9B;;CAGA,QAAQ,IAAY;EAClB,MAAM,EAAE,SAAS,UAAU;EAC3B,IAAI,UAAU,GAAG,OAAO;EACxB,IAAI,MAAM,GAAG,OAAO,KAAK,YAAY,GAAG,CAAC;EACzC,IAAI,MAAM,KAAK,OAAO,OAAO,KAAK,YAAY,QAAQ,GAAG,EAAE;EAC3D,IAAI,MAAM;EACV,IAAI,OAAO,QAAQ;EAEnB,OAAO,MAAM,MAAM;GACjB,MAAM,MAAO,MAAM,OAAO,KAAM;GAChC,IAAI,QAAQ,QAAS,IAAI,MAAM;QAC1B,OAAO,MAAM;EACpB;EACA,OAAO,KAAK,YAAY,KAAK,EAAE;CACjC;;CAGA,YAAY,OAAe,MAAc;EACvC,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI,KAAK,OAAO,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO,CAAC,GAAG,OAAO;EACrF,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI,KAAK,OAAO,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO,CAAC,GAAG,OAAO;EACrF,OAAO;CACT;AACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/core/cell-type.ts
|
|
2
|
+
/** Declares a cell type; only gives it a type. */
|
|
3
|
+
function defineSheetCellType(type) {
|
|
4
|
+
return type;
|
|
5
|
+
}
|
|
6
|
+
var bare = /* @__PURE__ */ new Map();
|
|
7
|
+
var setupOf = (name) => {
|
|
8
|
+
let setup = bare.get(name);
|
|
9
|
+
if (!setup) bare.set(name, setup = { type: name });
|
|
10
|
+
return setup;
|
|
11
|
+
};
|
|
12
|
+
/** The type of a cell, or `undefined` when it has none or the type isn't known. */
|
|
13
|
+
function resolveCellType(cell, book, types) {
|
|
14
|
+
const name = cell?.type;
|
|
15
|
+
if (!name) return void 0;
|
|
16
|
+
const setup = book.types?.[name] ?? setupOf(name);
|
|
17
|
+
const definition = types.get(setup.type);
|
|
18
|
+
return definition ? {
|
|
19
|
+
name: definition.name,
|
|
20
|
+
definition,
|
|
21
|
+
setup
|
|
22
|
+
} : void 0;
|
|
23
|
+
}
|
|
24
|
+
/** A `select` option as a value with an optional tone. */
|
|
25
|
+
function optionOf(option) {
|
|
26
|
+
return option !== null && typeof option === "object" ? option : { value: option };
|
|
27
|
+
}
|
|
28
|
+
export { defineSheetCellType, optionOf, resolveCellType };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=cell-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cell-type.js","names":[],"sources":["../../src/core/cell-type.ts"],"sourcesContent":["import type { Component } from 'vue'\nimport type { SheetMessages } from '../locale'\nimport type { SheetInput } from './format'\nimport type {\n SheetCell,\n SheetSelectOption,\n SheetTypeSetup,\n SheetValue,\n SheetWorkbook,\n} from './model'\n\n/*\n * Cell types. A cell's `type` names one, directly (`'date'`) or through a\n * named setup in the workbook's `types` (`'status'` →\n * `{ type: 'select', options: [...] }`). The type decides how the value\n * shows, what typed text becomes, and what opens beside the editor.\n */\n\n/** What a type's `render` component gets. */\nexport interface SheetCellRenderProps {\n value: SheetValue\n /** The value as text, formatted as the cell would show it. */\n text: string\n setup: SheetTypeSetup\n /** Whether the grid is read-only. */\n readonly: boolean\n}\n\n/** What a type's `panel` component gets. */\nexport interface SheetCellPanelProps {\n /** The value in the cell when editing began. */\n value: SheetValue\n /** What is typed in the editor now. */\n text: string\n /** Whether anything was typed since editing began. */\n typed: boolean\n setup: SheetTypeSetup\n}\n\n/**\n * What a type's `panel` may expose: keys the editor passes on first, e.g.\n * the arrow keys to move through a list. Return `true` when handled.\n */\nexport interface SheetCellPanelExpose {\n onKey?: (event: KeyboardEvent) => boolean\n}\n\nexport interface SheetCellType {\n /** The name cells refer to with `type`. */\n name: string\n /**\n * Reads typed or pasted text. Return `undefined` to read it as any cell\n * does (numbers, dates, `TRUE`…).\n */\n parse?: (text: string, setup: SheetTypeSetup) => SheetInput | undefined\n /**\n * The text shown for a value; by default the value with the cell's\n * `format`. Copying and screen readers use it too.\n */\n format?: (value: SheetValue, setup: SheetTypeSetup) => string | undefined\n /**\n * The text the editor starts with, which `parse` reads back. By default\n * the text `format` gives, or the value as typed when there is no `format`.\n */\n edit?: (value: SheetValue, setup: SheetTypeSetup) => string | undefined\n /**\n * Whether a value fits the type: `true`, or `false` or a short sentence\n * saying why not, e.g. text in a date cell. A cell whose value doesn't fit\n * gets a small mark in its corner; the sentence shows on hover and is read\n * out. Empty cells always fit.\n */\n valid?: (value: SheetValue, setup: SheetTypeSetup, messages: SheetMessages) => boolean | string\n /**\n * Drawn in the cell instead of its text; props are `SheetCellRenderProps`.\n * Keep it light: it is drawn for every visible cell of the type. An\n * element in it with `data-sheet-toggle` switches the value on a click.\n */\n render?: Component\n /**\n * Shown under the cell while it is edited, such as a calendar. Props are\n * `SheetCellPanelProps`; emit `pick` with a value to write it and finish.\n */\n panel?: Component\n /**\n * Switches the value instead of opening the editor: on `Space`, `F2`, a\n * double click or a click on a `data-sheet-toggle` element. `Space`\n * switches every selected cell of the type: all to the same value when\n * they hold the same, otherwise all to what an empty cell switches to.\n */\n toggle?: (value: SheetValue, setup: SheetTypeSetup) => SheetValue\n /** Where the content sits when the cell's style doesn't say. */\n align?: 'left' | 'center' | 'right'\n /**\n * The value written into files for other spreadsheet programs, such as a\n * number for a rating; by default the value itself. Exporters read it as\n * `source.plain`.\n */\n plain?: (value: SheetValue, setup: SheetTypeSetup) => SheetValue\n /**\n * What the cell shows in pictures of the sheet (`png`, `svg` and printing),\n * as SVG markup in the cell's own coordinates, from its top left corner,\n * kept to the cell. Text put in the markup must go through `draw.escape`.\n * Not asked for empty cells or formula errors, which show as text. By\n * default the cell's text; a type with `render` draws its own content\n * here, as pictures can't hold components.\n */\n draw?: (value: SheetValue, setup: SheetTypeSetup, draw: SheetDrawContext) => string\n}\n\n/** A place in a cell's picture, in the cell's own coordinates. */\nexport interface SheetDrawRect {\n x: number\n y: number\n width: number\n height: number\n}\n\n/** How `draw.text` writes text; by default as the cell's look says. */\nexport interface SheetDrawTextOptions {\n align?: 'left' | 'center' | 'right'\n valign?: 'top' | 'middle' | 'bottom'\n /** A color as SVG takes it, e.g. from `draw.color`. */\n color?: string\n bold?: boolean\n italic?: boolean\n /** In px. */\n size?: number\n}\n\n/** What a cell type's `draw` gets: the cell's size and look, and tools to draw with. */\nexport interface SheetDrawContext {\n /** The cell's size. */\n width: number\n height: number\n /** The text the cell shows, as `format` gives it. */\n formatted: string\n /** The cell's look, in colors SVG takes. */\n look: {\n color: string\n /** The fill, `null` for none. */\n background: string | null\n align: 'left' | 'center' | 'right'\n valign: 'top' | 'middle' | 'bottom'\n bold: boolean\n italic: boolean\n fontFamily: string\n /** In px. */\n fontSize: number\n }\n /** Text on one line in a box (the whole cell by default), escaped, in the cell's look unless `options` say otherwise. */\n text: (value: string, box?: SheetDrawRect, options?: SheetDrawTextOptions) => string\n /** An icon component, e.g. from `@dou-ui/icons`, as SVG. */\n icon: (icon: Component, box: SheetDrawRect, color: string) => string\n /**\n * A CSS color, also one with variables such as `var(--dou-color-primary)`,\n * as a color every SVG reader understands, read in the sheet's theme.\n */\n color: (value: string) => string\n /** Escapes text for SVG markup. */\n escape: (text: string) => string\n}\n\n/** Declares a cell type; only gives it a type. */\nexport function defineSheetCellType(type: SheetCellType): SheetCellType {\n return type\n}\n\n/** A cell's type, resolved: its name, what defines it and its settings. */\nexport interface SheetResolvedType {\n /** The cell type's name, e.g. `select` for a cell whose `type` is a setup of a list. */\n name: string\n definition: SheetCellType\n setup: SheetTypeSetup\n}\n\nconst bare = new Map<string, SheetTypeSetup>()\nconst setupOf = (name: string) => {\n let setup = bare.get(name)\n if (!setup) bare.set(name, (setup = { type: name }))\n return setup\n}\n\n/** The type of a cell, or `undefined` when it has none or the type isn't known. */\nexport function resolveCellType(\n cell: SheetCell | undefined,\n book: SheetWorkbook,\n types: ReadonlyMap<string, SheetCellType>,\n): SheetResolvedType | undefined {\n const name = cell?.type\n if (!name) return undefined\n const setup = book.types?.[name] ?? setupOf(name)\n const definition = types.get(setup.type)\n return definition ? { name: definition.name, definition, setup } : undefined\n}\n\n/** A `select` option as a value with an optional tone. */\nexport function optionOf(option: SheetSelectOption) {\n return option !== null && typeof option === 'object' ? option : { value: option }\n}\n"],"mappings":";;AAmKA,SAAgB,oBAAoB,MAAoC;CACtE,OAAO;AACT;AAUA,IAAM,uBAAO,IAAI,IAA4B;AAC7C,IAAM,WAAW,SAAiB;CAChC,IAAI,QAAQ,KAAK,IAAI,IAAI;CACzB,IAAI,CAAC,OAAO,KAAK,IAAI,MAAO,QAAQ,EAAE,MAAM,KAAK,CAAE;CACnD,OAAO;AACT;;AAGA,SAAgB,gBACd,MACA,MACA,OAC+B;CAC/B,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,MAAM,QAAQ,KAAK,QAAQ,SAAS,QAAQ,IAAI;CAChD,MAAM,aAAa,MAAM,IAAI,MAAM,IAAI;CACvC,OAAO,aAAa;EAAE,MAAM,WAAW;EAAM;EAAY;CAAM,IAAI,KAAA;AACrE;;AAGA,SAAgB,SAAS,QAA2B;CAClD,OAAO,WAAW,QAAQ,OAAO,WAAW,WAAW,SAAS,EAAE,OAAO,OAAO;AAClF"}
|