@dou-ui/pivot 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.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/assets/default-PXde2wzm.js.map +1 -0
  4. package/dist/core/format.js +116 -0
  5. package/dist/core/format.js.map +1 -0
  6. package/dist/core/labels.js +28 -0
  7. package/dist/core/labels.js.map +1 -0
  8. package/dist/core/layout.js +190 -0
  9. package/dist/core/layout.js.map +1 -0
  10. package/dist/core/source.js +46 -0
  11. package/dist/core/source.js.map +1 -0
  12. package/dist/core/table.js +154 -0
  13. package/dist/core/table.js.map +1 -0
  14. package/dist/engine/aggregate.js +51 -0
  15. package/dist/engine/aggregate.js.map +1 -0
  16. package/dist/engine/compute.js +735 -0
  17. package/dist/engine/compute.js.map +1 -0
  18. package/dist/engine/engine.js +46 -0
  19. package/dist/engine/engine.js.map +1 -0
  20. package/dist/engine/formula.js +225 -0
  21. package/dist/engine/formula.js.map +1 -0
  22. package/dist/engine/group.js +107 -0
  23. package/dist/engine/group.js.map +1 -0
  24. package/dist/engine/hash.js +108 -0
  25. package/dist/engine/hash.js.map +1 -0
  26. package/dist/engine/index.js +8 -0
  27. package/dist/engine/show.js +132 -0
  28. package/dist/engine/show.js.map +1 -0
  29. package/dist/engine/source.js +339 -0
  30. package/dist/engine/source.js.map +1 -0
  31. package/dist/engine/tree.js +226 -0
  32. package/dist/engine/tree.js.map +1 -0
  33. package/dist/fields/fields.js +6 -0
  34. package/dist/fields/fields.js.map +1 -0
  35. package/dist/fields/fields.vue_vue_type_script_setup_true_lang.js +881 -0
  36. package/dist/fields/fields.vue_vue_type_script_setup_true_lang.js.map +1 -0
  37. package/dist/fields/filter-list.js +6 -0
  38. package/dist/fields/filter-list.js.map +1 -0
  39. package/dist/fields/filter-list.vue_vue_type_script_setup_true_lang.js +184 -0
  40. package/dist/fields/filter-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/fields/formula-dialog.js +6 -0
  42. package/dist/fields/formula-dialog.js.map +1 -0
  43. package/dist/fields/formula-dialog.vue_vue_type_script_setup_true_lang.js +165 -0
  44. package/dist/fields/formula-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  45. package/dist/fields/model.js +200 -0
  46. package/dist/fields/model.js.map +1 -0
  47. package/dist/fields/top-dialog.js +6 -0
  48. package/dist/fields/top-dialog.js.map +1 -0
  49. package/dist/fields/top-dialog.vue_vue_type_script_setup_true_lang.js +174 -0
  50. package/dist/fields/top-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/index.js +16 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/locale.js +508 -0
  54. package/dist/locale.js.map +1 -0
  55. package/dist/pivot.js +6 -0
  56. package/dist/pivot.js.map +1 -0
  57. package/dist/pivot.vue_vue_type_script_setup_true_lang.js +1711 -0
  58. package/dist/pivot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/style.css +1 -0
  60. package/dist/style.d.ts +1 -0
  61. package/dist/style.js +13 -0
  62. package/dist/types/core/format.d.ts +26 -0
  63. package/dist/types/core/labels.d.ts +14 -0
  64. package/dist/types/core/layout.d.ts +72 -0
  65. package/dist/types/core/source.d.ts +7 -0
  66. package/dist/types/core/table.d.ts +73 -0
  67. package/dist/types/engine/aggregate.d.ts +35 -0
  68. package/dist/types/engine/compute.d.ts +173 -0
  69. package/dist/types/engine/engine.d.ts +29 -0
  70. package/dist/types/engine/formula.d.ts +44 -0
  71. package/dist/types/engine/group.d.ts +34 -0
  72. package/dist/types/engine/hash.d.ts +36 -0
  73. package/dist/types/engine/index.d.ts +15 -0
  74. package/dist/types/engine/show.d.ts +27 -0
  75. package/dist/types/engine/source.d.ts +108 -0
  76. package/dist/types/engine/tree.d.ts +87 -0
  77. package/dist/types/engine/types.d.ts +148 -0
  78. package/dist/types/fields/fields.vue.d.ts +26 -0
  79. package/dist/types/fields/filter-list.vue.d.ts +20 -0
  80. package/dist/types/fields/formula-dialog.vue.d.ts +30 -0
  81. package/dist/types/fields/model.d.ts +52 -0
  82. package/dist/types/fields/top-dialog.vue.d.ts +25 -0
  83. package/dist/types/index.d.ts +458 -0
  84. package/dist/types/locale.d.ts +184 -0
  85. package/dist/types/pivot.vue.d.ts +29 -0
  86. package/dist/types/types.d.ts +199 -0
  87. package/dist/types/worker/client.d.ts +19 -0
  88. package/dist/types/worker/default.d.ts +1 -0
  89. package/dist/types/worker/index.d.ts +5 -0
  90. package/dist/types/worker/protocol.d.ts +60 -0
  91. package/dist/types/worker/serve.d.ts +22 -0
  92. package/dist/worker/client.js +191 -0
  93. package/dist/worker/client.js.map +1 -0
  94. package/dist/worker/default.js +20 -0
  95. package/dist/worker/default.js.map +1 -0
  96. package/dist/worker/index.js +3 -0
  97. package/dist/worker/serve.js +101 -0
  98. package/dist/worker/serve.js.map +1 -0
  99. package/package.json +64 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_unref","_createBlock","_withCtx","_createVNode","_createTextVNode","_toDisplayString","_createCommentVNode","_resolveDynamicComponent","_mergeProps","_createElementVNode","_Fragment","_renderList","FilterList","FormulaDialog","TopDialog"],"sources":["../../src/fields/fields.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"Row = Record<string, unknown>\">\nimport type { HTMLAttributes } from 'vue'\nimport type { ForwardedAttributes } from 'dou-ui'\nimport {\n DouButton,\n DouCheckbox,\n DouDrawer,\n DouDropdown,\n DouDropdownItem,\n DouDropdownRadioGroup,\n DouDropdownSub,\n DouInput,\n DouPopover,\n DouSortable,\n useBreakpoints,\n} from 'dou-ui'\nimport {\n CalendarIcon,\n ChevronDownIcon,\n FilterIcon,\n HashIcon,\n LayoutThreeColumnsIcon,\n LayoutThreeRowsIcon,\n PlusIcon,\n SearchIcon,\n SigmaIcon,\n TablePivotIcon,\n ToggleLeftIcon,\n TypeIcon,\n} from '@dou-ui/icons'\nimport { computed, nextTick, onMounted, ref, useId, type Component } from 'vue'\nimport {\n resolveConfig,\n type PivotAggregator,\n type PivotResolvedField,\n type PivotShowAs,\n type PivotSource,\n} from '../engine'\nimport { BUILTIN_AGGREGATORS } from '../engine/aggregate'\nimport { DATE_PERIODS, groupKey, type PivotGroupBy } from '../engine/group'\nimport type { PivotConfig, PivotDimension, PivotFieldType, PivotFilter } from '../engine/types'\nimport { valueLabel } from '../core/labels'\nimport { usePivotSource } from '../core/source'\nimport { format, usePivotMessages } from '../locale'\nimport type { PivotFieldsProps } from '../types'\nimport FilterList from './filter-list.vue'\nimport FormulaDialog from './formula-dialog.vue'\nimport TopDialog from './top-dialog.vue'\nimport {\n areasOf,\n AREAS,\n configOf,\n isFiltering,\n moveItem,\n stepsFor,\n withAggregate,\n withDimension,\n withFilter,\n withRank,\n withValue,\n type PivotArea,\n type PivotAreas,\n type PivotFieldItem,\n type PivotRank,\n} from './model'\n\ndefineOptions({ name: 'DouPivotFields' })\n\nconst props = withDefaults(\n defineProps<\n PivotFieldsProps<Row> &\n /* @vue-ignore */ ForwardedAttributes<HTMLAttributes, PivotFieldsProps<Row>>\n >(),\n { drawer: 'auto' },\n)\nconst config = defineModel<PivotConfig>('config', { default: () => ({}) })\n\nconst messages = usePivotMessages(() => props.messages)\nconst source = usePivotSource(\n () => props.data,\n () => props.fields,\n)\nconst group = `dou-pivot-fields-${useId()}`\n\n// ---- the fields ----\n\nconst TYPE_ICON: Record<PivotFieldType, Component> = {\n string: TypeIcon,\n number: HashIcon,\n date: CalendarIcon,\n boolean: ToggleLeftIcon,\n}\nconst AREA_ICON: Record<PivotArea, Component> = {\n filters: FilterIcon,\n columns: LayoutThreeColumnsIcon,\n rows: LayoutThreeRowsIcon,\n values: SigmaIcon,\n}\n\nconst allFields = computed<PivotResolvedField<unknown>[]>(() => {\n const s = source.value\n // the source knows each listed field, and makes one up for any other key the config names\n return [...s.fields.values()] as PivotResolvedField<unknown>[]\n})\nconst field = (name: string) => source.value.field(name) as PivotResolvedField<unknown>\n\nconst query = ref('')\nconst listItems = computed<PivotFieldItem[]>({\n get: () => {\n const q = query.value.trim().toLocaleLowerCase()\n return allFields.value\n .filter((f) => !q || f.label.toLocaleLowerCase().includes(q) || f.name.includes(q))\n .map((f, index): PivotFieldItem => ({\n key: `l:${f.name}`,\n kind: 'field',\n field: f.name,\n index,\n }))\n },\n // the list always shows every field: dragging one out copies it\n set: () => {},\n})\n\nconst areas = computed(() => areasOf(config.value))\nconst used = computed(() => {\n const set = new Set<string>()\n for (const area of AREAS) for (const item of areas.value[area]) set.add(item.field)\n return set\n})\n\n// ---- moving fields ----\n\nlet pending: PivotAreas | null = null\n/** One drop updates two lists (the one left and the one entered); both land in one change. */\nfunction setArea(area: PivotArea, items: PivotFieldItem[]) {\n if (!pending) {\n pending = { ...areas.value }\n queueMicrotask(() => {\n const next = pending!\n pending = null\n config.value = configOf(next, config.value)\n })\n }\n pending[area] = items\n}\n\nconst areaModel = (area: PivotArea) =>\n computed<PivotFieldItem[]>({\n get: () => areas.value[area],\n set: (items) => setArea(area, items),\n })\nconst models = Object.fromEntries(AREAS.map((a) => [a, areaModel(a)])) as Record<\n PivotArea,\n ReturnType<typeof areaModel>\n>\n\nconst areaOf = (item: PivotFieldItem): PivotArea | null =>\n AREAS.find((a) => areas.value[a].some((i) => i.key === item.key)) ?? null\n\nfunction moveTo(item: PivotFieldItem, to: PivotArea | null) {\n config.value = configOf(moveItem(areas.value, areaOf(item), item, to), config.value)\n}\n\n/** Moves an item one place up or down in its area. */\nfunction shift(item: PivotFieldItem, by: -1 | 1) {\n const area = areaOf(item)\n if (!area) return\n const list = [...areas.value[area]]\n const at = list.findIndex((i) => i.key === item.key)\n const to = at + by\n if (to < 0 || to >= list.length) return\n list.splice(at, 1)\n list.splice(to, 0, item)\n config.value = configOf({ ...areas.value, [area]: list }, config.value)\n}\nconst placeOf = (item: PivotFieldItem) => {\n const area = areaOf(item)\n const list = area ? areas.value[area] : []\n return { first: list[0]?.key === item.key, last: list[list.length - 1]?.key === item.key }\n}\n\n/** The checkbox in the list: adds a field where it fits (numbers to the values), or takes it out everywhere. */\nfunction toggleField(name: string, on: boolean) {\n if (!on) {\n let next = areas.value\n for (const area of AREAS) next = { ...next, [area]: next[area].filter((i) => i.field !== name) }\n config.value = configOf(next, config.value)\n return\n }\n const item: PivotFieldItem = { key: `l:${name}`, kind: 'field', field: name, index: 0 }\n moveTo(item, field(name).type === 'number' ? 'values' : 'rows')\n}\n\nconst itemLabel = (item: PivotFieldItem) => (item.field ? field(item.field).label : '')\n\n// ---- what each chip shows ----\n\nconst resolved = computed(() => {\n try {\n return resolveConfig(source.value as never, config.value, { aggregators: aggregatorMap.value })\n } catch {\n return null\n }\n})\nconst aggregatorMap = computed(() => {\n const map: Record<string, PivotAggregator> = {}\n for (const a of props.aggregators ?? []) map[a.name] = a\n return map\n})\n\n/** How a grouping reads, as in the grouping menu. */\nfunction groupText(by: PivotGroupBy) {\n const m = messages.value.fields\n if (typeof by === 'string') return m.periods[by]\n const write = new Intl.NumberFormat(undefined, { maximumFractionDigits: 6 })\n return format(m.step, { step: write.format(by.step) })\n}\n\n/** A chip's grouping, shown apart from its name so it can go on a line of its own. */\nfunction chipGroup(item: PivotFieldItem) {\n if (item.kind !== 'dimension') return ''\n const by = dimensionOf(axisOf(item), item.field)?.by\n const top = topText(item.field)\n return [by === undefined ? '' : groupText(by), top].filter(Boolean).join(' · ')\n}\n\n/** How a field's top N or range reads (\"前 10 项\", \"合计 ≥ 100\"), or ''. */\nfunction topText(name: string) {\n const filter = filterOf(name)\n const m = messages.value.fields\n if (filter?.top) {\n return format(filter.top.order === 'asc' ? m.bottomN : m.topN, { count: filter.top.count })\n }\n if (filter?.between) {\n const write = new Intl.NumberFormat(undefined, { maximumFractionDigits: 6 })\n const { min, max } = filter.between\n const range =\n min !== undefined && max !== undefined\n ? format(messages.value.rangeLabel, { from: write.format(min), to: write.format(max) })\n : min !== undefined\n ? `≥ ${write.format(min)}`\n : `≤ ${write.format(max ?? 0)}`\n return format(m.between, { range })\n }\n return ''\n}\n\nconst chipName = (item: PivotFieldItem) =>\n item.kind === 'dimension' ? itemLabel(item) : chipText(item)\n\nfunction chipText(item: PivotFieldItem) {\n if (item.kind === 'dimension') {\n const extra = chipGroup(item)\n return extra\n ? format(messages.value.fields.grouped, { field: itemLabel(item), group: extra })\n : itemLabel(item)\n }\n if (item.kind !== 'value') return itemLabel(item)\n const value = resolved.value?.values[item.index]\n const given = config.value.values?.[item.index]\n if (!value) return item.field ? itemLabel(item) : messages.value.aggregates.count!\n return valueLabel(value, typeof given === 'object' ? given.label : undefined, messages.value)\n}\n\nconst dimensionOf = (axis: 'rows' | 'columns', name: string) => {\n const d = (config.value[axis] ?? []).find((x) => (typeof x === 'string' ? x : x.field) === name)\n return (typeof d === 'string' ? { field: d } : d) as Exclude<PivotDimension, string> | undefined\n}\n\nconst filterOf = (name: string) => config.value.filters?.[name]\n\n/** Whether a field's values can be filtered from its chip (not a value: it sums the field up). */\nconst canFilter = (item: PivotFieldItem) => item.kind !== 'value' && !!item.field\n\n// ---- the menus ----\n\nconst aggregatesFor = (name: string) => {\n const type = name ? field(name).type : 'string'\n const builtIn =\n type === 'number'\n ? ['sum', 'count', 'avg', 'min', 'max', 'distinct', 'median']\n : type === 'date'\n ? ['count', 'distinct', 'min', 'max']\n : ['count', 'distinct']\n const custom = (props.aggregators ?? [])\n .filter((a) => type === 'number' || a.input === 'value')\n .map((a) => a.name)\n return [...builtIn, ...custom.filter((n) => !builtIn.includes(n))]\n}\nconst aggregateText = (name: string) =>\n messages.value.aggregates[name] ??\n aggregatorMap.value[name]?.label ??\n BUILTIN_AGGREGATORS[name]?.label ??\n name\n\nconst currentAggregate = (index: number) => resolved.value?.values[index]?.aggregate ?? 'count'\n\n/** The groupings a field offers: periods for dates, round range sizes for numbers. */\nfunction groupingsFor(name: string): { key: string; by: PivotGroupBy | null; text: string }[] {\n const f = field(name)\n const m = messages.value.fields\n const none = { key: '', by: null, text: m.noGroup }\n if (f.type === 'date')\n return [none, ...DATE_PERIODS.map((p) => ({ key: p, by: p, text: m.periods[p] }))]\n if (f.type !== 'number') return []\n const measure = source.value.measure(name)\n let min = Infinity\n let max = -Infinity\n for (let i = 0; i < measure.length; i++) {\n const v = measure[i]!\n if (v < min) min = v\n if (v > max) max = v\n }\n const write = new Intl.NumberFormat(undefined, { maximumFractionDigits: 6 })\n return [\n none,\n ...stepsFor(min, max).map((step) => ({\n key: groupKey({ step }),\n by: { step },\n text: format(m.step, { step: write.format(step) }),\n })),\n ]\n}\n\n/** The sort a row field's menu shows: by its labels, or the rows by a value's grand total. */\nfunction sortKey(axis: 'rows' | 'columns', name: string) {\n const sort = config.value.sort\n if (axis === 'rows' && sort && !sort.column?.length) return `v:${sort.valueIndex}:${sort.order}`\n return dimensionOf(axis, name)?.sort ?? 'asc'\n}\nfunction onSort(axis: 'rows' | 'columns', name: string, key: string | number) {\n const by = /^v:(\\d+):(asc|desc)$/.exec(String(key))\n if (by) {\n const order = by[2] as 'asc' | 'desc'\n config.value = { ...config.value, sort: { valueIndex: +by[1]!, column: [], order } }\n return\n }\n const next = withDimension(config.value, axis, name, { sort: key as 'asc' | 'desc' })\n // sorting by labels on the rows takes over from sorting by a value\n if (axis === 'rows') next.sort = null\n config.value = next\n}\nfunction onGroup(axis: 'rows' | 'columns', name: string, key: string | number) {\n const option = groupingsFor(name).find((g) => g.key === key)\n if (!option) return\n config.value = withDimension(config.value, axis, name, { by: option.by })\n}\nfunction onSubtotal(axis: 'rows' | 'columns', name: string, on: boolean) {\n config.value = withDimension(config.value, axis, name, { subtotal: on })\n}\nfunction onAggregate(index: number, name: string | number) {\n config.value = withAggregate(config.value, index, String(name))\n}\n\n// ---- showing values ----\n\nconst SHOWS: PivotShowAs[] = [\n 'percentOfTotal',\n 'percentOfRow',\n 'percentOfColumn',\n 'percentOfParent',\n 'difference',\n 'percentDifference',\n 'runningTotal',\n 'rank',\n]\nconst valueSpec = (index: number) => {\n const v = config.value.values?.[index]\n return typeof v === 'object' ? v : undefined\n}\nconst showKey = (index: number) => {\n const show = valueSpec(index)?.show\n return show === undefined ? '' : typeof show === 'string' ? show : show.as\n}\nfunction onShow(index: number, key: string | number) {\n const spec = valueSpec(index)?.show\n const axis = typeof spec === 'object' ? spec.axis : undefined\n const show = key === '' ? null : axis ? { as: key as PivotShowAs, axis } : (key as PivotShowAs)\n config.value = withValue(config.value, index, { show: show as PivotShowAs | null })\n}\nconst markKey = (index: number) => {\n const mark = valueSpec(index)?.mark\n return mark === undefined ? '' : typeof mark === 'string' ? mark : mark.type\n}\nfunction onMark(index: number, key: string | number) {\n config.value = withValue(config.value, index, {\n mark: key === '' ? null : (key as 'bar' | 'scale'),\n })\n}\n\n// ---- top N ----\n\nconst TOPS = [\n { key: 't5', count: 5, order: 'desc' },\n { key: 't10', count: 10, order: 'desc' },\n { key: 't20', count: 20, order: 'desc' },\n { key: 'b5', count: 5, order: 'asc' },\n { key: 'b10', count: 10, order: 'asc' },\n] as const\nfunction topKey(name: string) {\n const filter = filterOf(name)\n if (filter?.between) return 'range'\n if (!filter?.top) return ''\n return `${filter.top.order === 'asc' ? 'b' : 't'}${filter.top.count}`\n}\nconst topOptions = (name: string) => {\n const m = messages.value.fields\n const options: { key: string; text: string }[] = [{ key: '', text: m.noTop }]\n for (const t of TOPS) {\n options.push({\n key: t.key,\n text: format(t.order === 'asc' ? m.bottomN : m.topN, { count: t.count }),\n })\n }\n // a top N or a range set elsewhere, which the list does not offer\n const key = topKey(name)\n if (key && !options.some((o) => o.key === key)) options.push({ key, text: topText(name) })\n return options\n}\nfunction onTop(item: PivotFieldItem, key: string | number) {\n if (key === 'range') return\n const match = /^([tb])(\\d+)$/.exec(String(key))\n const old = filterOf(item.field)?.top\n setRank(\n item,\n match\n ? {\n top: {\n ...(old?.valueIndex ? { valueIndex: old.valueIndex } : {}),\n count: Number(match[2]),\n ...(match[1] === 'b' ? { order: 'asc' as const } : {}),\n },\n }\n : null,\n )\n}\nfunction setRank(item: PivotFieldItem, rank: PivotRank | null) {\n config.value = withRank(config.value, item.field, rank, item.kind === 'filter')\n}\n\n/** The field whose top N or range is set in the dialog. */\nconst topItem = ref<PivotFieldItem | null>(null)\nconst topOpen = ref(false)\nfunction openTop(item: PivotFieldItem) {\n topItem.value = item\n // after the menu has closed and given focus back\n nextTick(() => (topOpen.value = true))\n}\n\n// ---- calculated values ----\n\nconst formulaOpen = ref(false)\n/** The value being changed in the dialog, or -1 for a new one. */\nconst formulaIndex = ref(-1)\nconst formulaInitial = computed(() => {\n const spec = formulaIndex.value >= 0 ? valueSpec(formulaIndex.value) : undefined\n return spec?.formula === undefined ? null : { formula: spec.formula, label: spec.label }\n})\nfunction openFormula(index: number) {\n formulaIndex.value = index\n // after a menu has closed and given focus back\n nextTick(() => (formulaOpen.value = true))\n}\nfunction applyFormula(value: { formula: string; label?: string }) {\n const index = formulaIndex.value\n if (index < 0) {\n config.value = { ...config.value, values: [...(config.value.values ?? []), value] }\n return\n }\n config.value = withValue(config.value, index, {\n formula: value.formula,\n label: value.label ?? null,\n })\n}\nconst isFormula = (item: PivotFieldItem) =>\n item.kind === 'value' && valueSpec(item.index)?.formula !== undefined\n\n// ---- filters ----\n\nconst filterOpen = ref<string | null>(null)\nfunction setFilterOpen(key: string, open: boolean) {\n if (open) filterOpen.value = key\n else if (filterOpen.value === key) filterOpen.value = null\n}\nfunction openFilter(item: PivotFieldItem) {\n // after the menu has closed and given focus back\n nextTick(() => (filterOpen.value = item.key))\n}\nconst filterBy = (item: PivotFieldItem): PivotGroupBy | undefined => {\n if (item.kind === 'dimension') {\n const axis = areas.value.rows.some((i) => i.key === item.key) ? 'rows' : 'columns'\n return dimensionOf(axis, item.field)?.by\n }\n return filterOf(item.field)?.by\n}\nfunction applyFilter(item: PivotFieldItem, filter: PivotFilter | null) {\n // the list sets which groups are picked; top N and ranges stay\n const old = filterOf(item.field)\n const kept = { top: old?.top, between: old?.between }\n if (kept.top || kept.between) {\n filter = {\n ...filter,\n ...(kept.top ? { top: kept.top } : {}),\n ...(kept.between ? { between: kept.between } : {}),\n }\n if (filter.by === undefined && old?.by !== undefined) filter.by = old.by\n }\n config.value = withFilter(config.value, item.field, filter, item.kind === 'filter')\n filterOpen.value = null\n}\n\n// ---- a narrow screen ----\n\nconst breakpoints = useBreakpoints()\nconst mounted = ref(false)\nonMounted(() => (mounted.value = true))\nconst inDrawer = computed(() =>\n props.drawer === 'auto' ? mounted.value && !breakpoints.sm : props.drawer,\n)\nconst drawerOpen = ref(false)\n\nconst areaTitle = (area: PivotArea) => messages.value.fields.areas[area]\n/** Where else an item can go; a count of records has no field to group or filter by. */\nconst otherAreas = (item: PivotFieldItem) => {\n const here = areaOf(item)\n return AREAS.filter((a) => a !== here && (item.field || a === 'values'))\n}\nconst axisOf = (item: PivotFieldItem) =>\n areas.value.rows.some((i) => i.key === item.key) ? ('rows' as const) : ('columns' as const)\n\nconst filtered = (item: PivotFieldItem) => isFiltering(filterOf(item.field))\n</script>\n\n<template>\n <div\n :class=\"inDrawer ? 'dou-pivot-fields-trigger' : 'dou-pivot-fields'\"\n :role=\"inDrawer ? undefined : 'region'\"\n :aria-label=\"inDrawer ? undefined : messages.fields.panel\"\n >\n <DouButton v-if=\"inDrawer\" size=\"sm\" variant=\"outline\" @click=\"drawerOpen = true\">\n <template #leading><TablePivotIcon aria-hidden=\"true\" /></template>\n {{ messages.fields.open }}\n </DouButton>\n <component\n :is=\"inDrawer ? DouDrawer : 'div'\"\n v-bind=\"\n inDrawer\n ? { open: drawerOpen, title: messages.fields.panel, placement: 'bottom', size: '80%' }\n : { class: 'dou-pivot-fields__inner' }\n \"\n @update:open=\"drawerOpen = $event\"\n >\n <div :class=\"inDrawer ? 'dou-pivot-fields is-in-drawer' : 'dou-pivot-fields__body'\">\n <section class=\"dou-pivot-fields__list-part\" :aria-label=\"messages.fields.list\">\n <DouInput\n v-model=\"query\"\n size=\"sm\"\n type=\"search\"\n clearable\n :placeholder=\"messages.fields.search\"\n :aria-label=\"messages.fields.search\"\n >\n <template #prefix><SearchIcon aria-hidden=\"true\" /></template>\n </DouInput>\n <DouSortable\n v-model=\"listItems\"\n class=\"dou-pivot-fields__list\"\n :group=\"group\"\n :animation=\"false\"\n item-key=\"key\"\n :item-label=\"(item) => itemLabel(item)\"\n >\n <template #default=\"{ item }\">\n <div class=\"dou-pivot-fields__field\">\n <DouCheckbox\n size=\"sm\"\n :model-value=\"used.has(item.field)\"\n :aria-label=\"itemLabel(item)\"\n @update:model-value=\"toggleField(item.field, !!$event)\"\n />\n <component\n :is=\"TYPE_ICON[field(item.field).type]\"\n class=\"dou-pivot-fields__type\"\n aria-hidden=\"true\"\n />\n <span class=\"dou-pivot-fields__name\">{{ itemLabel(item) }}</span>\n </div>\n </template>\n <template #empty>\n <p class=\"dou-pivot-fields__none\">{{ messages.fields.noFields }}</p>\n </template>\n </DouSortable>\n </section>\n\n <div class=\"dou-pivot-fields__areas\">\n <section\n v-for=\"area in AREAS\"\n :key=\"area\"\n class=\"dou-pivot-fields__area\"\n :class=\"`is-${area}`\"\n :aria-label=\"areaTitle(area)\"\n >\n <h3 class=\"dou-pivot-fields__area-title\">\n <component :is=\"AREA_ICON[area]\" aria-hidden=\"true\" />\n {{ areaTitle(area) }}\n </h3>\n <DouSortable\n v-model=\"models[area].value\"\n class=\"dou-pivot-fields__chips\"\n :group=\"group\"\n item-key=\"key\"\n :item-label=\"(item) => chipText(item)\"\n >\n <template #default=\"{ item }\">\n <div class=\"dou-pivot-fields__chip\" :class=\"{ 'is-filtered': filtered(item) }\">\n <span class=\"dou-pivot-fields__chip-text\" :title=\"chipText(item)\">\n <span class=\"dou-pivot-fields__chip-name\">{{ chipName(item) }}</span>\n <span v-if=\"chipGroup(item)\" class=\"dou-pivot-fields__chip-group\">{{\n chipGroup(item)\n }}</span>\n </span>\n <DouPopover\n v-if=\"canFilter(item)\"\n :open=\"filterOpen === item.key\"\n placement=\"bottom-start\"\n :width=\"260\"\n @update:open=\"setFilterOpen(item.key, $event)\"\n >\n <button\n type=\"button\"\n class=\"dou-pivot-fields__chip-button\"\n :class=\"{ 'is-on': filtered(item) }\"\n :aria-label=\"\n filtered(item)\n ? `${messages.fields.filtered},${format(messages.filter.title, { field: itemLabel(item) })}`\n : format(messages.filter.title, { field: itemLabel(item) })\n \"\n >\n <FilterIcon aria-hidden=\"true\" />\n </button>\n <template #content>\n <!-- a fresh list each time it opens, picked as the filter is now -->\n <FilterList\n :key=\"filterOpen === item.key ? 'open' : 'closed'\"\n :source=\"source as never\"\n :field=\"item.field\"\n :by=\"filterBy(item)\"\n :filter=\"filterOf(item.field)\"\n :messages=\"messages\"\n @apply=\"applyFilter(item, $event)\"\n @cancel=\"filterOpen = null\"\n />\n </template>\n </DouPopover>\n <DouDropdown placement=\"bottom-end\">\n <button\n type=\"button\"\n class=\"dou-pivot-fields__chip-button\"\n :aria-label=\"format(messages.fields.menu, { field: chipText(item) })\"\n >\n <ChevronDownIcon aria-hidden=\"true\" />\n </button>\n <template #menu>\n <template v-if=\"item.kind === 'dimension'\">\n <DouDropdownSub :title=\"messages.fields.sort\">\n <DouDropdownRadioGroup\n :model-value=\"sortKey(axisOf(item), item.field)\"\n @update:model-value=\"onSort(axisOf(item), item.field, $event!)\"\n >\n <DouDropdownItem value=\"asc\">{{ messages.fields.asc }}</DouDropdownItem>\n <DouDropdownItem value=\"desc\">{{\n messages.fields.desc\n }}</DouDropdownItem>\n <template v-if=\"axisOf(item) === 'rows'\">\n <template v-for=\"(value, index) in areas.values\" :key=\"value.key\">\n <DouDropdownItem\n :value=\"`v:${index}:desc`\"\n :divided=\"index === 0\"\n >{{\n format(messages.fields.byValueDesc, { value: chipText(value) })\n }}</DouDropdownItem\n >\n <DouDropdownItem :value=\"`v:${index}:asc`\">{{\n format(messages.fields.byValueAsc, { value: chipText(value) })\n }}</DouDropdownItem>\n </template>\n </template>\n </DouDropdownRadioGroup>\n </DouDropdownSub>\n <DouDropdownSub\n v-if=\"groupingsFor(item.field).length\"\n :title=\"messages.fields.groupBy\"\n >\n <DouDropdownRadioGroup\n :model-value=\"groupKey(dimensionOf(axisOf(item), item.field)?.by)\"\n @update:model-value=\"onGroup(axisOf(item), item.field, $event!)\"\n >\n <DouDropdownItem\n v-for=\"option in groupingsFor(item.field)\"\n :key=\"option.key\"\n :value=\"option.key\"\n >{{ option.text }}</DouDropdownItem\n >\n </DouDropdownRadioGroup>\n </DouDropdownSub>\n <DouDropdownSub :title=\"messages.fields.top\">\n <DouDropdownRadioGroup\n :model-value=\"topKey(item.field)\"\n @update:model-value=\"onTop(item, $event!)\"\n >\n <DouDropdownItem\n v-for=\"option in topOptions(item.field)\"\n :key=\"option.key\"\n :value=\"option.key\"\n :divided=\"option.key === 'b5'\"\n >{{ option.text }}</DouDropdownItem\n >\n </DouDropdownRadioGroup>\n <DouDropdownItem divided @click=\"openTop(item)\">{{\n messages.fields.customTop\n }}</DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem\n :checked=\"dimensionOf(axisOf(item), item.field)?.subtotal !== false\"\n @update:checked=\"onSubtotal(axisOf(item), item.field, $event)\"\n >{{ messages.fields.subtotal }}</DouDropdownItem\n >\n </template>\n <template v-if=\"item.kind === 'value'\">\n <DouDropdownItem v-if=\"isFormula(item)\" @click=\"openFormula(item.index)\">{{\n messages.fields.editFormula\n }}</DouDropdownItem>\n <DouDropdownSub v-else :title=\"messages.fields.aggregate\">\n <DouDropdownRadioGroup\n :model-value=\"currentAggregate(item.index)\"\n @update:model-value=\"onAggregate(item.index, $event!)\"\n >\n <DouDropdownItem\n v-for=\"name in aggregatesFor(item.field)\"\n :key=\"name\"\n :value=\"name\"\n >{{ aggregateText(name) }}</DouDropdownItem\n >\n </DouDropdownRadioGroup>\n </DouDropdownSub>\n <DouDropdownSub :title=\"messages.fields.showAs\">\n <DouDropdownRadioGroup\n :model-value=\"showKey(item.index)\"\n @update:model-value=\"onShow(item.index, $event!)\"\n >\n <DouDropdownItem value=\"\">{{\n messages.fields.showPlain\n }}</DouDropdownItem>\n <DouDropdownItem\n v-for=\"(show, i) in SHOWS\"\n :key=\"show\"\n :value=\"show\"\n :divided=\"i === 0 || show === 'difference'\"\n >{{ messages.shows[show] }}</DouDropdownItem\n >\n </DouDropdownRadioGroup>\n </DouDropdownSub>\n <DouDropdownSub :title=\"messages.fields.mark\">\n <DouDropdownRadioGroup\n :model-value=\"markKey(item.index)\"\n @update:model-value=\"onMark(item.index, $event!)\"\n >\n <DouDropdownItem value=\"\">{{ messages.fields.noMark }}</DouDropdownItem>\n <DouDropdownItem value=\"bar\">{{ messages.fields.bar }}</DouDropdownItem>\n <DouDropdownItem value=\"scale\">{{\n messages.fields.scale\n }}</DouDropdownItem>\n </DouDropdownRadioGroup>\n </DouDropdownSub>\n <DouDropdownItem\n v-if=\"(config.values?.length ?? 0) > 1\"\n :checked=\"config.valuesOn === 'rows'\"\n @update:checked=\"\n config = { ...config, valuesOn: $event ? 'rows' : 'columns' }\n \"\n >{{ messages.fields.valuesOnRows }}</DouDropdownItem\n >\n </template>\n <DouDropdownItem v-if=\"canFilter(item)\" @click=\"openFilter(item)\">{{\n messages.fields.filter\n }}</DouDropdownItem>\n <DouDropdownItem\n divided\n :disabled=\"placeOf(item).first\"\n @click=\"shift(item, -1)\"\n >{{ messages.fields.moveUp }}</DouDropdownItem\n >\n <DouDropdownItem :disabled=\"placeOf(item).last\" @click=\"shift(item, 1)\">{{\n messages.fields.moveDown\n }}</DouDropdownItem>\n <DouDropdownSub :title=\"messages.fields.moveTo\">\n <DouDropdownItem\n v-for=\"to in otherAreas(item)\"\n :key=\"to\"\n @click=\"moveTo(item, to)\"\n >{{ areaTitle(to) }}</DouDropdownItem\n >\n </DouDropdownSub>\n <DouDropdownItem tone=\"danger\" @click=\"moveTo(item, null)\">{{\n messages.fields.remove\n }}</DouDropdownItem>\n </template>\n </DouDropdown>\n </div>\n </template>\n <template #empty>\n <p class=\"dou-pivot-fields__drop\">{{ messages.fields.dropHere }}</p>\n </template>\n </DouSortable>\n <DouButton\n v-if=\"area === 'values'\"\n class=\"dou-pivot-fields__add\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"openFormula(-1)\"\n >\n <template #leading><PlusIcon aria-hidden=\"true\" /></template>\n {{ messages.fields.addFormula }}\n </DouButton>\n </section>\n </div>\n </div>\n </component>\n <FormulaDialog\n v-model:open=\"formulaOpen\"\n :source=\"source as PivotSource<unknown>\"\n :messages=\"messages\"\n :initial=\"formulaInitial\"\n @apply=\"applyFormula\"\n />\n <TopDialog\n v-model:open=\"topOpen\"\n :messages=\"messages\"\n :field=\"topItem ? itemLabel(topItem) : ''\"\n :values=\"areas.values.map((v) => chipText(v))\"\n :filter=\"topItem ? filterOf(topItem.field) : undefined\"\n @apply=\"topItem && setRank(topItem, $event)\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import filter_list_vue_vue_type_script_setup_true_lang_default from "./filter-list.vue_vue_type_script_setup_true_lang.js";
2
+ // src/fields/filter-list.vue
3
+ var filter_list_default = filter_list_vue_vue_type_script_setup_true_lang_default;
4
+ export { filter_list_default as default };
5
+
6
+ //# sourceMappingURL=filter-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-list.js","names":["_sfc_main"],"sources":["../../src/fields/filter-list.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouButton, DouCheckbox, DouInput, DouVirtualList, useLocale } from 'dou-ui'\nimport { SearchIcon } from '@dou-ui/icons'\nimport { computed, ref, shallowRef } from 'vue'\nimport type { PivotSource } from '../engine'\nimport type { PivotGroupBy } from '../engine/group'\nimport type { PivotFilter } from '../engine/types'\nimport { labelFormatter } from '../core/format'\nimport { format, type PivotMessages } from '../locale'\n\nconst props = defineProps<{\n source: PivotSource<unknown>\n field: string\n by?: PivotGroupBy\n filter?: PivotFilter\n messages: PivotMessages\n}>()\nconst emit = defineEmits<{ apply: [filter: PivotFilter | null]; cancel: [] }>()\n\nconst ROW = 32\nconst { locale } = useLocale()\n\n/** Each group of the field, in its natural order, with how many records it has. */\nconst groups = computed(() => {\n const column = props.source.dimension(props.field, props.by)\n const m = props.messages\n const write = labelFormatter(\n props.source.field(props.field),\n locale.value.name,\n {\n empty: m.empty,\n yes: m.yes,\n no: m.no,\n year: m.yearLabel,\n quarter: m.quarterLabel,\n week: m.weekLabel,\n range: m.rangeLabel,\n },\n props.by,\n )\n const counts = new Uint32Array(column.labels.length)\n for (let i = 0; i < column.codes.length; i++) counts[column.codes[i]!]!++\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n const order = Array.from(column.labels.keys()).sort((a, b) => column.rank[a]! - column.rank[b]!)\n return order.map((code) => ({\n code,\n value: column.labels[code],\n text: write(column.labels[code]),\n count: counts[code]!,\n }))\n})\n\n/** Picked groups, by group number; starts from the filter as it is. */\nconst picked = shallowRef(initial())\nfunction initial() {\n const column = props.source.dimension(props.field, props.by)\n const keep = new Uint8Array(column.labels.length)\n const f = props.filter\n if (f?.include) for (const v of f.include) mark(keep, column.find(v), 1)\n else {\n keep.fill(1)\n for (const v of f?.exclude ?? []) mark(keep, column.find(v), 0)\n }\n return keep\n}\nfunction mark(keep: Uint8Array, code: number, to: 0 | 1) {\n if (code >= 0) keep[code] = to\n}\n\nconst query = ref('')\nconst shown = computed(() => {\n const q = query.value.trim().toLocaleLowerCase()\n return q ? groups.value.filter((g) => g.text.toLocaleLowerCase().includes(q)) : groups.value\n})\n\nconst pickedCount = computed(() => picked.value.reduce((n, v) => n + v, 0))\nconst shownPicked = computed(() => shown.value.filter((g) => picked.value[g.code]).length)\nconst allShown = computed(() => shown.value.length > 0 && shownPicked.value === shown.value.length)\n\nfunction toggle(code: number, on: boolean) {\n const next = picked.value.slice()\n next[code] = on ? 1 : 0\n picked.value = next\n}\nfunction toggleShown(on: boolean) {\n const next = picked.value.slice()\n for (const g of shown.value) next[g.code] = on ? 1 : 0\n picked.value = next\n}\n\nfunction apply() {\n const total = groups.value.length\n const count = pickedCount.value\n if (count === total) return emit('apply', null)\n const keep = picked.value\n const values = (on: number) => groups.value.filter((g) => keep[g.code] === on).map((g) => g.value)\n // the shorter list; leaving some out keeps groups that show up later\n const filter: PivotFilter =\n total - count <= count ? { exclude: values(0) } : { include: values(1) }\n if (props.by !== undefined) filter.by = props.by\n emit('apply', filter)\n}\n\nconst fieldLabel = computed(() => props.source.field(props.field).label)\n</script>\n\n<template>\n <div\n class=\"dou-pivot-filter\"\n role=\"group\"\n :aria-label=\"format(messages.filter.title, { field: fieldLabel })\"\n >\n <DouInput\n v-model=\"query\"\n class=\"dou-pivot-filter__search\"\n size=\"sm\"\n type=\"search\"\n clearable\n :placeholder=\"messages.filter.search\"\n :aria-label=\"messages.filter.search\"\n >\n <template #prefix><SearchIcon aria-hidden=\"true\" /></template>\n </DouInput>\n <div class=\"dou-pivot-filter__all\">\n <DouCheckbox\n :model-value=\"allShown\"\n :indeterminate=\"shownPicked > 0 && !allShown\"\n :disabled=\"!shown.length\"\n size=\"sm\"\n @update:model-value=\"toggleShown(!!$event)\"\n >\n {{ messages.filter.all }}\n </DouCheckbox>\n </div>\n <DouVirtualList\n v-if=\"shown.length\"\n class=\"dou-pivot-filter__list\"\n :items=\"shown\"\n :item-size=\"ROW\"\n item-key=\"code\"\n :height=\"Math.min(shown.length * ROW, ROW * 8)\"\n >\n <template #default=\"{ item }\">\n <div class=\"dou-pivot-filter__item\">\n <DouCheckbox\n :model-value=\"!!picked[item.code]\"\n size=\"sm\"\n @update:model-value=\"toggle(item.code, !!$event)\"\n >\n <span class=\"dou-pivot-filter__text\">{{ item.text }}</span>\n </DouCheckbox>\n <span class=\"dou-pivot-filter__count\">{{ item.count.toLocaleString(locale.name) }}</span>\n </div>\n </template>\n </DouVirtualList>\n <p v-else class=\"dou-pivot-filter__none\">{{ messages.filter.noMatch }}</p>\n <div class=\"dou-pivot-filter__foot\">\n <span class=\"dou-pivot-filter__picked\">{{\n format(messages.filter.count, { picked: pickedCount, total: groups.length })\n }}</span>\n <DouButton size=\"sm\" variant=\"ghost\" @click=\"emit('cancel')\">{{\n messages.filter.cancel\n }}</DouButton>\n <DouButton size=\"sm\" tone=\"primary\" :disabled=\"pickedCount === 0\" @click=\"apply\">{{\n messages.filter.apply\n }}</DouButton>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,184 @@
1
+ import { labelFormatter } from "../core/format.js";
2
+ import { format } from "../locale.js";
3
+ import { DouButton, DouCheckbox, DouInput, DouVirtualList, useLocale } from "dou-ui";
4
+ import { computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, ref, shallowRef, toDisplayString, unref, withCtx } from "vue";
5
+ import { SearchIcon } from "@dou-ui/icons";
6
+ // src/fields/filter-list.vue?vue&type=script&setup=true&lang.ts
7
+ var _hoisted_1 = ["aria-label"];
8
+ var _hoisted_2 = { class: "dou-pivot-filter__all" };
9
+ var _hoisted_3 = { class: "dou-pivot-filter__item" };
10
+ var _hoisted_4 = { class: "dou-pivot-filter__text" };
11
+ var _hoisted_5 = { class: "dou-pivot-filter__count" };
12
+ var _hoisted_6 = {
13
+ key: 1,
14
+ class: "dou-pivot-filter__none"
15
+ };
16
+ var _hoisted_7 = { class: "dou-pivot-filter__foot" };
17
+ var _hoisted_8 = { class: "dou-pivot-filter__picked" };
18
+ var ROW = 32;
19
+ var filter_list_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
20
+ __name: "filter-list",
21
+ props: {
22
+ source: {},
23
+ field: {},
24
+ by: {},
25
+ filter: {},
26
+ messages: {}
27
+ },
28
+ emits: ["apply", "cancel"],
29
+ setup(__props, { emit: __emit }) {
30
+ const props = __props;
31
+ const emit = __emit;
32
+ const { locale } = useLocale();
33
+ /** Each group of the field, in its natural order, with how many records it has. */
34
+ const groups = computed(() => {
35
+ const column = props.source.dimension(props.field, props.by);
36
+ const m = props.messages;
37
+ const write = labelFormatter(props.source.field(props.field), locale.value.name, {
38
+ empty: m.empty,
39
+ yes: m.yes,
40
+ no: m.no,
41
+ year: m.yearLabel,
42
+ quarter: m.quarterLabel,
43
+ week: m.weekLabel,
44
+ range: m.rangeLabel
45
+ }, props.by);
46
+ const counts = new Uint32Array(column.labels.length);
47
+ for (let i = 0; i < column.codes.length; i++) counts[column.codes[i]]++;
48
+ return Array.from(column.labels.keys()).sort((a, b) => column.rank[a] - column.rank[b]).map((code) => ({
49
+ code,
50
+ value: column.labels[code],
51
+ text: write(column.labels[code]),
52
+ count: counts[code]
53
+ }));
54
+ });
55
+ /** Picked groups, by group number; starts from the filter as it is. */
56
+ const picked = shallowRef(initial());
57
+ function initial() {
58
+ const column = props.source.dimension(props.field, props.by);
59
+ const keep = new Uint8Array(column.labels.length);
60
+ const f = props.filter;
61
+ if (f?.include) for (const v of f.include) mark(keep, column.find(v), 1);
62
+ else {
63
+ keep.fill(1);
64
+ for (const v of f?.exclude ?? []) mark(keep, column.find(v), 0);
65
+ }
66
+ return keep;
67
+ }
68
+ function mark(keep, code, to) {
69
+ if (code >= 0) keep[code] = to;
70
+ }
71
+ const query = ref("");
72
+ const shown = computed(() => {
73
+ const q = query.value.trim().toLocaleLowerCase();
74
+ return q ? groups.value.filter((g) => g.text.toLocaleLowerCase().includes(q)) : groups.value;
75
+ });
76
+ const pickedCount = computed(() => picked.value.reduce((n, v) => n + v, 0));
77
+ const shownPicked = computed(() => shown.value.filter((g) => picked.value[g.code]).length);
78
+ const allShown = computed(() => shown.value.length > 0 && shownPicked.value === shown.value.length);
79
+ function toggle(code, on) {
80
+ const next = picked.value.slice();
81
+ next[code] = on ? 1 : 0;
82
+ picked.value = next;
83
+ }
84
+ function toggleShown(on) {
85
+ const next = picked.value.slice();
86
+ for (const g of shown.value) next[g.code] = on ? 1 : 0;
87
+ picked.value = next;
88
+ }
89
+ function apply() {
90
+ const total = groups.value.length;
91
+ const count = pickedCount.value;
92
+ if (count === total) return emit("apply", null);
93
+ const keep = picked.value;
94
+ const values = (on) => groups.value.filter((g) => keep[g.code] === on).map((g) => g.value);
95
+ const filter = total - count <= count ? { exclude: values(0) } : { include: values(1) };
96
+ if (props.by !== void 0) filter.by = props.by;
97
+ emit("apply", filter);
98
+ }
99
+ const fieldLabel = computed(() => props.source.field(props.field).label);
100
+ return (_ctx, _cache) => {
101
+ return openBlock(), createElementBlock("div", {
102
+ class: "dou-pivot-filter",
103
+ role: "group",
104
+ "aria-label": unref(format)(__props.messages.filter.title, { field: fieldLabel.value })
105
+ }, [
106
+ createVNode(unref(DouInput), {
107
+ modelValue: query.value,
108
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => query.value = $event),
109
+ class: "dou-pivot-filter__search",
110
+ size: "sm",
111
+ type: "search",
112
+ clearable: "",
113
+ placeholder: __props.messages.filter.search,
114
+ "aria-label": __props.messages.filter.search
115
+ }, {
116
+ prefix: withCtx(() => [createVNode(unref(SearchIcon), { "aria-hidden": "true" })]),
117
+ _: 1
118
+ }, 8, [
119
+ "modelValue",
120
+ "placeholder",
121
+ "aria-label"
122
+ ]),
123
+ createElementVNode("div", _hoisted_2, [createVNode(unref(DouCheckbox), {
124
+ "model-value": allShown.value,
125
+ indeterminate: shownPicked.value > 0 && !allShown.value,
126
+ disabled: !shown.value.length,
127
+ size: "sm",
128
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => toggleShown(!!$event))
129
+ }, {
130
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.messages.filter.all), 1)]),
131
+ _: 1
132
+ }, 8, [
133
+ "model-value",
134
+ "indeterminate",
135
+ "disabled"
136
+ ])]),
137
+ shown.value.length ? (openBlock(), createBlock(unref(DouVirtualList), {
138
+ key: 0,
139
+ class: "dou-pivot-filter__list",
140
+ items: shown.value,
141
+ "item-size": ROW,
142
+ "item-key": "code",
143
+ height: Math.min(shown.value.length * ROW, 256)
144
+ }, {
145
+ default: withCtx(({ item }) => [createElementVNode("div", _hoisted_3, [createVNode(unref(DouCheckbox), {
146
+ "model-value": !!picked.value[item.code],
147
+ size: "sm",
148
+ "onUpdate:modelValue": ($event) => toggle(item.code, !!$event)
149
+ }, {
150
+ default: withCtx(() => [createElementVNode("span", _hoisted_4, toDisplayString(item.text), 1)]),
151
+ _: 2
152
+ }, 1032, ["model-value", "onUpdate:modelValue"]), createElementVNode("span", _hoisted_5, toDisplayString(item.count.toLocaleString(unref(locale).name)), 1)])]),
153
+ _: 1
154
+ }, 8, ["items", "height"])) : (openBlock(), createElementBlock("p", _hoisted_6, toDisplayString(__props.messages.filter.noMatch), 1)),
155
+ createElementVNode("div", _hoisted_7, [
156
+ createElementVNode("span", _hoisted_8, toDisplayString(unref(format)(__props.messages.filter.count, {
157
+ picked: pickedCount.value,
158
+ total: groups.value.length
159
+ })), 1),
160
+ createVNode(unref(DouButton), {
161
+ size: "sm",
162
+ variant: "ghost",
163
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("cancel"))
164
+ }, {
165
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.messages.filter.cancel), 1)]),
166
+ _: 1
167
+ }),
168
+ createVNode(unref(DouButton), {
169
+ size: "sm",
170
+ tone: "primary",
171
+ disabled: pickedCount.value === 0,
172
+ onClick: apply
173
+ }, {
174
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.messages.filter.apply), 1)]),
175
+ _: 1
176
+ }, 8, ["disabled"])
177
+ ])
178
+ ], 8, _hoisted_1);
179
+ };
180
+ }
181
+ });
182
+ export { filter_list_vue_vue_type_script_setup_true_lang_default as default };
183
+
184
+ //# sourceMappingURL=filter-list.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-list.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_unref","_createVNode","_withCtx","_createElementVNode","_createTextVNode","_toDisplayString","_createBlock"],"sources":["../../src/fields/filter-list.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouButton, DouCheckbox, DouInput, DouVirtualList, useLocale } from 'dou-ui'\nimport { SearchIcon } from '@dou-ui/icons'\nimport { computed, ref, shallowRef } from 'vue'\nimport type { PivotSource } from '../engine'\nimport type { PivotGroupBy } from '../engine/group'\nimport type { PivotFilter } from '../engine/types'\nimport { labelFormatter } from '../core/format'\nimport { format, type PivotMessages } from '../locale'\n\nconst props = defineProps<{\n source: PivotSource<unknown>\n field: string\n by?: PivotGroupBy\n filter?: PivotFilter\n messages: PivotMessages\n}>()\nconst emit = defineEmits<{ apply: [filter: PivotFilter | null]; cancel: [] }>()\n\nconst ROW = 32\nconst { locale } = useLocale()\n\n/** Each group of the field, in its natural order, with how many records it has. */\nconst groups = computed(() => {\n const column = props.source.dimension(props.field, props.by)\n const m = props.messages\n const write = labelFormatter(\n props.source.field(props.field),\n locale.value.name,\n {\n empty: m.empty,\n yes: m.yes,\n no: m.no,\n year: m.yearLabel,\n quarter: m.quarterLabel,\n week: m.weekLabel,\n range: m.rangeLabel,\n },\n props.by,\n )\n const counts = new Uint32Array(column.labels.length)\n for (let i = 0; i < column.codes.length; i++) counts[column.codes[i]!]!++\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n const order = Array.from(column.labels.keys()).sort((a, b) => column.rank[a]! - column.rank[b]!)\n return order.map((code) => ({\n code,\n value: column.labels[code],\n text: write(column.labels[code]),\n count: counts[code]!,\n }))\n})\n\n/** Picked groups, by group number; starts from the filter as it is. */\nconst picked = shallowRef(initial())\nfunction initial() {\n const column = props.source.dimension(props.field, props.by)\n const keep = new Uint8Array(column.labels.length)\n const f = props.filter\n if (f?.include) for (const v of f.include) mark(keep, column.find(v), 1)\n else {\n keep.fill(1)\n for (const v of f?.exclude ?? []) mark(keep, column.find(v), 0)\n }\n return keep\n}\nfunction mark(keep: Uint8Array, code: number, to: 0 | 1) {\n if (code >= 0) keep[code] = to\n}\n\nconst query = ref('')\nconst shown = computed(() => {\n const q = query.value.trim().toLocaleLowerCase()\n return q ? groups.value.filter((g) => g.text.toLocaleLowerCase().includes(q)) : groups.value\n})\n\nconst pickedCount = computed(() => picked.value.reduce((n, v) => n + v, 0))\nconst shownPicked = computed(() => shown.value.filter((g) => picked.value[g.code]).length)\nconst allShown = computed(() => shown.value.length > 0 && shownPicked.value === shown.value.length)\n\nfunction toggle(code: number, on: boolean) {\n const next = picked.value.slice()\n next[code] = on ? 1 : 0\n picked.value = next\n}\nfunction toggleShown(on: boolean) {\n const next = picked.value.slice()\n for (const g of shown.value) next[g.code] = on ? 1 : 0\n picked.value = next\n}\n\nfunction apply() {\n const total = groups.value.length\n const count = pickedCount.value\n if (count === total) return emit('apply', null)\n const keep = picked.value\n const values = (on: number) => groups.value.filter((g) => keep[g.code] === on).map((g) => g.value)\n // the shorter list; leaving some out keeps groups that show up later\n const filter: PivotFilter =\n total - count <= count ? { exclude: values(0) } : { include: values(1) }\n if (props.by !== undefined) filter.by = props.by\n emit('apply', filter)\n}\n\nconst fieldLabel = computed(() => props.source.field(props.field).label)\n</script>\n\n<template>\n <div\n class=\"dou-pivot-filter\"\n role=\"group\"\n :aria-label=\"format(messages.filter.title, { field: fieldLabel })\"\n >\n <DouInput\n v-model=\"query\"\n class=\"dou-pivot-filter__search\"\n size=\"sm\"\n type=\"search\"\n clearable\n :placeholder=\"messages.filter.search\"\n :aria-label=\"messages.filter.search\"\n >\n <template #prefix><SearchIcon aria-hidden=\"true\" /></template>\n </DouInput>\n <div class=\"dou-pivot-filter__all\">\n <DouCheckbox\n :model-value=\"allShown\"\n :indeterminate=\"shownPicked > 0 && !allShown\"\n :disabled=\"!shown.length\"\n size=\"sm\"\n @update:model-value=\"toggleShown(!!$event)\"\n >\n {{ messages.filter.all }}\n </DouCheckbox>\n </div>\n <DouVirtualList\n v-if=\"shown.length\"\n class=\"dou-pivot-filter__list\"\n :items=\"shown\"\n :item-size=\"ROW\"\n item-key=\"code\"\n :height=\"Math.min(shown.length * ROW, ROW * 8)\"\n >\n <template #default=\"{ item }\">\n <div class=\"dou-pivot-filter__item\">\n <DouCheckbox\n :model-value=\"!!picked[item.code]\"\n size=\"sm\"\n @update:model-value=\"toggle(item.code, !!$event)\"\n >\n <span class=\"dou-pivot-filter__text\">{{ item.text }}</span>\n </DouCheckbox>\n <span class=\"dou-pivot-filter__count\">{{ item.count.toLocaleString(locale.name) }}</span>\n </div>\n </template>\n </DouVirtualList>\n <p v-else class=\"dou-pivot-filter__none\">{{ messages.filter.noMatch }}</p>\n <div class=\"dou-pivot-filter__foot\">\n <span class=\"dou-pivot-filter__picked\">{{\n format(messages.filter.count, { picked: pickedCount, total: groups.length })\n }}</span>\n <DouButton size=\"sm\" variant=\"ghost\" @click=\"emit('cancel')\">{{\n messages.filter.cancel\n }}</DouButton>\n <DouButton size=\"sm\" tone=\"primary\" :disabled=\"pickedCount === 0\" @click=\"apply\">{{\n messages.filter.apply\n }}</DouButton>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAM,MAAM;;;;;;;;;;;;EATZ,MAAM,QAAQ;EAOd,MAAM,OAAO;EAGb,MAAM,EAAE,WAAW,UAAU;;EAG7B,MAAM,SAAS,eAAe;GAC5B,MAAM,SAAS,MAAM,OAAO,UAAU,MAAM,OAAO,MAAM,EAAE;GAC3D,MAAM,IAAI,MAAM;GAChB,MAAM,QAAQ,eACZ,MAAM,OAAO,MAAM,MAAM,KAAK,GAC9B,OAAO,MAAM,MACb;IACE,OAAO,EAAE;IACT,KAAK,EAAE;IACP,IAAI,EAAE;IACN,MAAM,EAAE;IACR,SAAS,EAAE;IACX,MAAM,EAAE;IACR,OAAO,EAAE;GACX,GACA,MAAM,EACR;GACA,MAAM,SAAS,IAAI,YAAY,OAAO,OAAO,MAAM;GACnD,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,MAAM,QAAQ,KAAK,OAAO,OAAO,MAAM,GAAI;GAGtE,OADc,MAAM,KAAK,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,OAAO,KAAK,KAAM,OAAO,KAAK,EACrF,CAAA,CAAM,KAAK,UAAU;IAC1B;IACA,OAAO,OAAO,OAAO;IACrB,MAAM,MAAM,OAAO,OAAO,KAAK;IAC/B,OAAO,OAAO;GAChB,EAAE;EACJ,CAAC;;EAGD,MAAM,SAAS,WAAW,QAAQ,CAAC;EACnC,SAAS,UAAU;GACjB,MAAM,SAAS,MAAM,OAAO,UAAU,MAAM,OAAO,MAAM,EAAE;GAC3D,MAAM,OAAO,IAAI,WAAW,OAAO,OAAO,MAAM;GAChD,MAAM,IAAI,MAAM;GAChB,IAAI,GAAG,SAAS,KAAK,MAAM,KAAK,EAAE,SAAS,KAAK,MAAM,OAAO,KAAK,CAAC,GAAG,CAAC;QAClE;IACH,KAAK,KAAK,CAAC;IACX,KAAK,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,KAAK,MAAM,OAAO,KAAK,CAAC,GAAG,CAAC;GAChE;GACA,OAAO;EACT;EACA,SAAS,KAAK,MAAkB,MAAc,IAAW;GACvD,IAAI,QAAQ,GAAG,KAAK,QAAQ;EAC9B;EAEA,MAAM,QAAQ,IAAI,EAAE;EACpB,MAAM,QAAQ,eAAe;GAC3B,MAAM,IAAI,MAAM,MAAM,KAAK,CAAC,CAAC,kBAAkB;GAC/C,OAAO,IAAI,OAAO,MAAM,QAAQ,MAAM,EAAE,KAAK,kBAAkB,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,OAAO;EACzF,CAAC;EAED,MAAM,cAAc,eAAe,OAAO,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC;EAC1E,MAAM,cAAc,eAAe,MAAM,MAAM,QAAQ,MAAM,OAAO,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM;EACzF,MAAM,WAAW,eAAe,MAAM,MAAM,SAAS,KAAK,YAAY,UAAU,MAAM,MAAM,MAAM;EAElG,SAAS,OAAO,MAAc,IAAa;GACzC,MAAM,OAAO,OAAO,MAAM,MAAM;GAChC,KAAK,QAAQ,KAAK,IAAI;GACtB,OAAO,QAAQ;EACjB;EACA,SAAS,YAAY,IAAa;GAChC,MAAM,OAAO,OAAO,MAAM,MAAM;GAChC,KAAK,MAAM,KAAK,MAAM,OAAO,KAAK,EAAE,QAAQ,KAAK,IAAI;GACrD,OAAO,QAAQ;EACjB;EAEA,SAAS,QAAQ;GACf,MAAM,QAAQ,OAAO,MAAM;GAC3B,MAAM,QAAQ,YAAY;GAC1B,IAAI,UAAU,OAAO,OAAO,KAAK,SAAS,IAAI;GAC9C,MAAM,OAAO,OAAO;GACpB,MAAM,UAAU,OAAe,OAAO,MAAM,QAAQ,MAAM,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK;GAEjG,MAAM,SACJ,QAAQ,SAAS,QAAQ,EAAE,SAAS,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,OAAO,CAAC,EAAE;GACzE,IAAI,MAAM,OAAO,KAAA,GAAW,OAAO,KAAK,MAAM;GAC9C,KAAK,SAAS,MAAM;EACtB;EAEA,MAAM,aAAa,eAAe,MAAM,OAAO,MAAM,MAAM,KAAK,CAAC,CAAC,KAAK;;GAIrE,OAAAA,UAAA,GAAAC,mBA4DM,OAAA;IA3DJ,OAAM;IACN,MAAK;IACJ,cAAYC,MAAA,MAAA,CAAM,CAAC,QAAA,SAAS,OAAO,OAAK,EAAA,OAAW,WAAA,MAAU,CAAA;;IAE9DC,YAUWD,MAAA,QAAA,GAAA;KATA,YAAA,MAAA;KAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,MAAK,QAAA;KACd,OAAM;KACN,MAAK;KACL,MAAK;KACL,WAAA;KACC,aAAa,QAAA,SAAS,OAAO;KAC7B,cAAY,QAAA,SAAS,OAAO;;KAElB,QAAME,cAAkC,CAAjCD,YAAiCD,MAAA,UAAA,GAAA,EAArB,eAAY,OAAM,CAAA,C;;;;;;;IAElDG,mBAUM,OAVN,YAUM,CATJF,YAQcD,MAAA,WAAA,GAAA;KAPX,eAAa,SAAA;KACb,eAAe,YAAA,QAAW,KAAA,CAAS,SAAA;KACnC,UAAQ,CAAG,MAAA,MAAM;KAClB,MAAK;KACJ,uBAAkB,OAAA,OAAA,OAAA,MAAA,WAAE,YAAW,CAAA,CAAG,MAAM;;KAEzC,SAAAE,cAAyB,CAAtBE,gBAAAC,gBAAA,QAAA,SAAS,OAAO,GAAG,GAAA,CAAA,C;;;;;;;IAIlB,MAAA,MAAM,UADdP,UAAA,GAAAQ,YAoBiBN,MAAA,cAAA,GAAA;;KAlBf,OAAM;KACL,OAAO,MAAA;KACP,aAAW;KACZ,YAAS;KACR,QAAQ,KAAK,IAAI,MAAA,MAAM,SAAS,KAAK,GAAG;;KAE9B,SAAOE,SAUV,EAVc,WAAI,CACxBC,mBASM,OATN,YASM,CARJF,YAMcD,MAAA,WAAA,GAAA;MALX,eAAW,CAAA,CAAI,OAAA,MAAO,KAAK;MAC5B,MAAK;MACJ,wBAAkB,WAAE,OAAO,KAAK,MAAI,CAAA,CAAI,MAAM;;MAE/C,SAAAE,cAA2D,CAA3DC,mBAA2D,QAA3D,YAA2DE,gBAAnB,KAAK,IAAI,GAAA,CAAA,C;;K,kDAEnDF,mBAAyF,QAAzF,YAAyFE,gBAAhD,KAAK,MAAM,eAAeL,MAAA,MAAA,CAAM,CAAC,IAAI,CAAA,GAAA,CAAA,C;;I,+BAIpFF,UAAA,GAAAC,mBAA0E,KAA1E,YAA0EM,gBAA9B,QAAA,SAAS,OAAO,OAAO,GAAA,CAAA;IACnEF,mBAUM,OAVN,YAUM;KATJA,mBAES,QAFT,YAESE,gBADPL,MAAA,MAAA,CAAM,CAAC,QAAA,SAAS,OAAO,OAAK;MAAA,QAAY,YAAA;MAAW,OAAS,OAAA,MAAO;KAAM,CAAA,CAAA,GAAA,CAAA;KAE3EC,YAEcD,MAAA,SAAA,GAAA;MAFH,MAAK;MAAK,SAAQ;MAAS,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,QAAA;;MAAY,SAAAE,cAE3D,CADAE,gBAAAC,gBAAA,QAAA,SAAS,OAAO,MAAM,GAAA,CAAA,C;;;KAExBJ,YAEcD,MAAA,SAAA,GAAA;MAFH,MAAK;MAAK,MAAK;MAAW,UAAU,YAAA,UAAW;MAAS,SAAO;;MAAO,SAAAE,cAE/E,CADAE,gBAAAC,gBAAA,QAAA,SAAS,OAAO,KAAK,GAAA,CAAA,C"}
@@ -0,0 +1,6 @@
1
+ import formula_dialog_vue_vue_type_script_setup_true_lang_default from "./formula-dialog.vue_vue_type_script_setup_true_lang.js";
2
+ // src/fields/formula-dialog.vue
3
+ var formula_dialog_default = formula_dialog_vue_vue_type_script_setup_true_lang_default;
4
+ export { formula_dialog_default as default };
5
+
6
+ //# sourceMappingURL=formula-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula-dialog.js","names":["_sfc_main"],"sources":["../../src/fields/formula-dialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouButton, DouDialog, DouForm, DouFormItem, DouInput, DouTextarea } from 'dou-ui'\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { checkPivotFormula, PivotFormulaError, type PivotSource } from '../engine'\nimport type { PivotMessages } from '../locale'\nimport { format } from '../locale'\n\nconst props = defineProps<{\n source: PivotSource<unknown>\n messages: PivotMessages\n /** The value being changed, or null for a new one. */\n initial: { formula: string; label?: string } | null\n}>()\nconst open = defineModel<boolean>('open', { required: true })\nconst emit = defineEmits<{ apply: [value: { formula: string; label?: string }] }>()\n\nconst name = ref('')\nconst text = ref('')\n/** Errors show once the formula has been edited, or on applying. */\nconst touched = ref(false)\nconst box = ref<InstanceType<typeof DouTextarea> | null>(null)\n\nwatch(open, (now) => {\n if (!now) return\n name.value = props.initial?.label ?? ''\n text.value = props.initial?.formula ?? ''\n touched.value = false\n})\n\nconst error = computed(() => {\n try {\n checkPivotFormula(props.source, text.value)\n return ''\n } catch (e) {\n if (!(e instanceof PivotFormulaError)) return String(e)\n return format(props.messages.formula.errors[e.code], { detail: e.detail })\n }\n})\n\n/** Number fields, to put in the formula by name. */\nconst numbers = computed(() => [...props.source.fields.values()].filter((f) => f.type === 'number'))\nconst SIMPLE = /^[\\p{L}_$][\\p{L}\\p{N}_$.]*$/u\nconst reference = (label: string, fieldName: string) => {\n // the label reads better; a name in brackets when the label is not one word or is taken\n const labels = [...props.source.fields.values()].filter((f) => f.label === label)\n const word = labels.length === 1 ? label : fieldName\n return SIMPLE.test(word) ? word : `[${word}]`\n}\n\nfunction insert(word: string) {\n const el = box.value?.textarea\n const at = el ? el.selectionStart : text.value.length\n const end = el ? el.selectionEnd : at\n const before = text.value.slice(0, at)\n const pad = before && !/[\\s(]$/.test(before) ? ' ' : ''\n text.value = `${before}${pad}${word}${text.value.slice(end)}`\n touched.value = true\n nextTick(() => {\n const caret = at + pad.length + word.length\n el?.focus()\n el?.setSelectionRange(caret, caret)\n })\n}\n\nfunction apply() {\n touched.value = true\n if (error.value) return\n const label = name.value.trim()\n emit('apply', { formula: text.value.trim(), ...(label ? { label } : {}) })\n open.value = false\n}\n</script>\n\n<template>\n <DouDialog v-model:open=\"open\" :title=\"messages.formula.title\" :width=\"440\">\n <DouForm layout=\"vertical\" class=\"dou-pivot-formula\" @submit=\"apply\">\n <DouFormItem :label=\"messages.formula.name\">\n <DouInput v-model=\"name\" :placeholder=\"messages.formula.namePlaceholder\" />\n </DouFormItem>\n <DouFormItem\n :label=\"messages.formula.formula\"\n :error=\"touched ? error : undefined\"\n :help=\"messages.formula.help\"\n >\n <DouTextarea\n ref=\"box\"\n v-model=\"text\"\n class=\"dou-pivot-formula__box\"\n :rows=\"2\"\n autosize\n :invalid=\"touched && !!error\"\n :placeholder=\"messages.formula.placeholder\"\n @update:model-value=\"touched = true\"\n @keydown.enter.exact.prevent=\"apply\"\n />\n </DouFormItem>\n <div v-if=\"numbers.length\" class=\"dou-pivot-formula__fields\">\n <span class=\"dou-pivot-formula__fields-title\">{{ messages.formula.fields }}</span>\n <DouButton\n v-for=\"f in numbers\"\n :key=\"f.name\"\n size=\"sm\"\n variant=\"outline\"\n @click=\"insert(reference(f.label, f.name))\"\n >{{ f.label }}</DouButton\n >\n </div>\n </DouForm>\n <template #footer=\"{ close }\">\n <DouButton variant=\"outline\" @click=\"close\">{{ messages.formula.cancel }}</DouButton>\n <DouButton variant=\"solid\" :disabled=\"touched && !!error\" @click=\"apply\">{{\n messages.formula.apply\n }}</DouButton>\n </template>\n </DouDialog>\n</template>\n"],"mappings":""}
@@ -0,0 +1,165 @@
1
+ import { PivotFormulaError } from "../engine/formula.js";
2
+ import { checkPivotFormula } from "../engine/compute.js";
3
+ import { format } from "../locale.js";
4
+ import { DouButton, DouDialog, DouForm, DouFormItem, DouInput, DouTextarea } from "dou-ui";
5
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, nextTick, openBlock, ref, renderList, toDisplayString, unref, useModel, watch, withCtx, withKeys, withModifiers } from "vue";
6
+ // src/fields/formula-dialog.vue?vue&type=script&setup=true&lang.ts
7
+ var _hoisted_1 = {
8
+ key: 0,
9
+ class: "dou-pivot-formula__fields"
10
+ };
11
+ var _hoisted_2 = { class: "dou-pivot-formula__fields-title" };
12
+ var formula_dialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
13
+ __name: "formula-dialog",
14
+ props: /*@__PURE__*/ mergeModels({
15
+ source: {},
16
+ messages: {},
17
+ initial: {}
18
+ }, {
19
+ "open": {
20
+ type: Boolean,
21
+ required: true
22
+ },
23
+ "openModifiers": {}
24
+ }),
25
+ emits: /*@__PURE__*/ mergeModels(["apply"], ["update:open"]),
26
+ setup(__props, { emit: __emit }) {
27
+ const props = __props;
28
+ const open = useModel(__props, "open");
29
+ const emit = __emit;
30
+ const name = ref("");
31
+ const text = ref("");
32
+ /** Errors show once the formula has been edited, or on applying. */
33
+ const touched = ref(false);
34
+ const box = ref(null);
35
+ watch(open, (now) => {
36
+ if (!now) return;
37
+ name.value = props.initial?.label ?? "";
38
+ text.value = props.initial?.formula ?? "";
39
+ touched.value = false;
40
+ });
41
+ const error = computed(() => {
42
+ try {
43
+ checkPivotFormula(props.source, text.value);
44
+ return "";
45
+ } catch (e) {
46
+ if (!(e instanceof PivotFormulaError)) return String(e);
47
+ return format(props.messages.formula.errors[e.code], { detail: e.detail });
48
+ }
49
+ });
50
+ /** Number fields, to put in the formula by name. */
51
+ const numbers = computed(() => [...props.source.fields.values()].filter((f) => f.type === "number"));
52
+ const SIMPLE = /^[\p{L}_$][\p{L}\p{N}_$.]*$/u;
53
+ const reference = (label, fieldName) => {
54
+ const word = [...props.source.fields.values()].filter((f) => f.label === label).length === 1 ? label : fieldName;
55
+ return SIMPLE.test(word) ? word : `[${word}]`;
56
+ };
57
+ function insert(word) {
58
+ const el = box.value?.textarea;
59
+ const at = el ? el.selectionStart : text.value.length;
60
+ const end = el ? el.selectionEnd : at;
61
+ const before = text.value.slice(0, at);
62
+ const pad = before && !/[\s(]$/.test(before) ? " " : "";
63
+ text.value = `${before}${pad}${word}${text.value.slice(end)}`;
64
+ touched.value = true;
65
+ nextTick(() => {
66
+ const caret = at + pad.length + word.length;
67
+ el?.focus();
68
+ el?.setSelectionRange(caret, caret);
69
+ });
70
+ }
71
+ function apply() {
72
+ touched.value = true;
73
+ if (error.value) return;
74
+ const label = name.value.trim();
75
+ emit("apply", {
76
+ formula: text.value.trim(),
77
+ ...label ? { label } : {}
78
+ });
79
+ open.value = false;
80
+ }
81
+ return (_ctx, _cache) => {
82
+ return openBlock(), createBlock(unref(DouDialog), {
83
+ open: open.value,
84
+ "onUpdate:open": _cache[3] || (_cache[3] = ($event) => open.value = $event),
85
+ title: __props.messages.formula.title,
86
+ width: 440
87
+ }, {
88
+ footer: withCtx(({ close }) => [createVNode(unref(DouButton), {
89
+ variant: "outline",
90
+ onClick: close
91
+ }, {
92
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.messages.formula.cancel), 1)]),
93
+ _: 1
94
+ }, 8, ["onClick"]), createVNode(unref(DouButton), {
95
+ variant: "solid",
96
+ disabled: touched.value && !!error.value,
97
+ onClick: apply
98
+ }, {
99
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.messages.formula.apply), 1)]),
100
+ _: 1
101
+ }, 8, ["disabled"])]),
102
+ default: withCtx(() => [createVNode(unref(DouForm), {
103
+ layout: "vertical",
104
+ class: "dou-pivot-formula",
105
+ onSubmit: apply
106
+ }, {
107
+ default: withCtx(() => [
108
+ createVNode(unref(DouFormItem), { label: __props.messages.formula.name }, {
109
+ default: withCtx(() => [createVNode(unref(DouInput), {
110
+ modelValue: name.value,
111
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => name.value = $event),
112
+ placeholder: __props.messages.formula.namePlaceholder
113
+ }, null, 8, ["modelValue", "placeholder"])]),
114
+ _: 1
115
+ }, 8, ["label"]),
116
+ createVNode(unref(DouFormItem), {
117
+ label: __props.messages.formula.formula,
118
+ error: touched.value ? error.value : void 0,
119
+ help: __props.messages.formula.help
120
+ }, {
121
+ default: withCtx(() => [createVNode(unref(DouTextarea), {
122
+ ref_key: "box",
123
+ ref: box,
124
+ modelValue: text.value,
125
+ "onUpdate:modelValue": [_cache[1] || (_cache[1] = ($event) => text.value = $event), _cache[2] || (_cache[2] = ($event) => touched.value = true)],
126
+ class: "dou-pivot-formula__box",
127
+ rows: 2,
128
+ autosize: "",
129
+ invalid: touched.value && !!error.value,
130
+ placeholder: __props.messages.formula.placeholder,
131
+ onKeydown: withKeys(withModifiers(apply, ["exact", "prevent"]), ["enter"])
132
+ }, null, 8, [
133
+ "modelValue",
134
+ "invalid",
135
+ "placeholder",
136
+ "onKeydown"
137
+ ])]),
138
+ _: 1
139
+ }, 8, [
140
+ "label",
141
+ "error",
142
+ "help"
143
+ ]),
144
+ numbers.value.length ? (openBlock(), createElementBlock("div", _hoisted_1, [createElementVNode("span", _hoisted_2, toDisplayString(__props.messages.formula.fields), 1), (openBlock(true), createElementBlock(Fragment, null, renderList(numbers.value, (f) => {
145
+ return openBlock(), createBlock(unref(DouButton), {
146
+ key: f.name,
147
+ size: "sm",
148
+ variant: "outline",
149
+ onClick: ($event) => insert(reference(f.label, f.name))
150
+ }, {
151
+ default: withCtx(() => [createTextVNode(toDisplayString(f.label), 1)]),
152
+ _: 2
153
+ }, 1032, ["onClick"]);
154
+ }), 128))])) : createCommentVNode("", true)
155
+ ]),
156
+ _: 1
157
+ })]),
158
+ _: 1
159
+ }, 8, ["open", "title"]);
160
+ };
161
+ }
162
+ });
163
+ export { formula_dialog_vue_vue_type_script_setup_true_lang_default as default };
164
+
165
+ //# sourceMappingURL=formula-dialog.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula-dialog.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","_unref","_withCtx","_createVNode","_createTextVNode","_toDisplayString","_withKeys","_withModifiers","_createElementBlock","_createElementVNode","_Fragment","_renderList","_createCommentVNode"],"sources":["../../src/fields/formula-dialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouButton, DouDialog, DouForm, DouFormItem, DouInput, DouTextarea } from 'dou-ui'\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { checkPivotFormula, PivotFormulaError, type PivotSource } from '../engine'\nimport type { PivotMessages } from '../locale'\nimport { format } from '../locale'\n\nconst props = defineProps<{\n source: PivotSource<unknown>\n messages: PivotMessages\n /** The value being changed, or null for a new one. */\n initial: { formula: string; label?: string } | null\n}>()\nconst open = defineModel<boolean>('open', { required: true })\nconst emit = defineEmits<{ apply: [value: { formula: string; label?: string }] }>()\n\nconst name = ref('')\nconst text = ref('')\n/** Errors show once the formula has been edited, or on applying. */\nconst touched = ref(false)\nconst box = ref<InstanceType<typeof DouTextarea> | null>(null)\n\nwatch(open, (now) => {\n if (!now) return\n name.value = props.initial?.label ?? ''\n text.value = props.initial?.formula ?? ''\n touched.value = false\n})\n\nconst error = computed(() => {\n try {\n checkPivotFormula(props.source, text.value)\n return ''\n } catch (e) {\n if (!(e instanceof PivotFormulaError)) return String(e)\n return format(props.messages.formula.errors[e.code], { detail: e.detail })\n }\n})\n\n/** Number fields, to put in the formula by name. */\nconst numbers = computed(() => [...props.source.fields.values()].filter((f) => f.type === 'number'))\nconst SIMPLE = /^[\\p{L}_$][\\p{L}\\p{N}_$.]*$/u\nconst reference = (label: string, fieldName: string) => {\n // the label reads better; a name in brackets when the label is not one word or is taken\n const labels = [...props.source.fields.values()].filter((f) => f.label === label)\n const word = labels.length === 1 ? label : fieldName\n return SIMPLE.test(word) ? word : `[${word}]`\n}\n\nfunction insert(word: string) {\n const el = box.value?.textarea\n const at = el ? el.selectionStart : text.value.length\n const end = el ? el.selectionEnd : at\n const before = text.value.slice(0, at)\n const pad = before && !/[\\s(]$/.test(before) ? ' ' : ''\n text.value = `${before}${pad}${word}${text.value.slice(end)}`\n touched.value = true\n nextTick(() => {\n const caret = at + pad.length + word.length\n el?.focus()\n el?.setSelectionRange(caret, caret)\n })\n}\n\nfunction apply() {\n touched.value = true\n if (error.value) return\n const label = name.value.trim()\n emit('apply', { formula: text.value.trim(), ...(label ? { label } : {}) })\n open.value = false\n}\n</script>\n\n<template>\n <DouDialog v-model:open=\"open\" :title=\"messages.formula.title\" :width=\"440\">\n <DouForm layout=\"vertical\" class=\"dou-pivot-formula\" @submit=\"apply\">\n <DouFormItem :label=\"messages.formula.name\">\n <DouInput v-model=\"name\" :placeholder=\"messages.formula.namePlaceholder\" />\n </DouFormItem>\n <DouFormItem\n :label=\"messages.formula.formula\"\n :error=\"touched ? error : undefined\"\n :help=\"messages.formula.help\"\n >\n <DouTextarea\n ref=\"box\"\n v-model=\"text\"\n class=\"dou-pivot-formula__box\"\n :rows=\"2\"\n autosize\n :invalid=\"touched && !!error\"\n :placeholder=\"messages.formula.placeholder\"\n @update:model-value=\"touched = true\"\n @keydown.enter.exact.prevent=\"apply\"\n />\n </DouFormItem>\n <div v-if=\"numbers.length\" class=\"dou-pivot-formula__fields\">\n <span class=\"dou-pivot-formula__fields-title\">{{ messages.formula.fields }}</span>\n <DouButton\n v-for=\"f in numbers\"\n :key=\"f.name\"\n size=\"sm\"\n variant=\"outline\"\n @click=\"insert(reference(f.label, f.name))\"\n >{{ f.label }}</DouButton\n >\n </div>\n </DouForm>\n <template #footer=\"{ close }\">\n <DouButton variant=\"outline\" @click=\"close\">{{ messages.formula.cancel }}</DouButton>\n <DouButton variant=\"solid\" :disabled=\"touched && !!error\" @click=\"apply\">{{\n messages.formula.apply\n }}</DouButton>\n </template>\n </DouDialog>\n</template>\n"],"mappings":"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"}