@panneau/lists 5.0.0-alpha.5 → 5.0.0-alpha.7

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 (63) hide show
  1. package/README.md +1 -1
  2. package/dist/ItemDetails.d.ts +4 -2
  3. package/dist/ItemDetails.d.ts.map +1 -1
  4. package/dist/ItemDetails.js +48 -6
  5. package/dist/ItemDetails.js.map +1 -1
  6. package/dist/List.js +54 -12
  7. package/dist/List.js.map +1 -1
  8. package/dist/ListSkeleton.d.ts +17 -0
  9. package/dist/ListSkeleton.d.ts.map +1 -0
  10. package/dist/ListSkeleton.js +111 -0
  11. package/dist/ListSkeleton.js.map +1 -0
  12. package/dist/ListView.d.ts +4 -1
  13. package/dist/ListView.d.ts.map +1 -1
  14. package/dist/ListView.js +494 -179
  15. package/dist/ListView.js.map +1 -1
  16. package/dist/actions/ActionButton.js +79 -21
  17. package/dist/actions/ActionButton.js.map +1 -1
  18. package/dist/actions/ConfirmDialog.js +121 -24
  19. package/dist/actions/ConfirmDialog.js.map +1 -1
  20. package/dist/actions/RowActions.js +1 -1
  21. package/dist/actions/RowActions.js.map +1 -1
  22. package/dist/actions/actions.js.map +1 -1
  23. package/dist/actions/icons.js.map +1 -1
  24. package/dist/cx.js.map +1 -1
  25. package/dist/displays/Displays.css +12 -0
  26. package/dist/displays/Displays.module.js +6 -2
  27. package/dist/displays/Displays.module.js.map +1 -1
  28. package/dist/displays/displays.d.ts +12 -0
  29. package/dist/displays/displays.d.ts.map +1 -1
  30. package/dist/displays/displays.js +310 -3
  31. package/dist/displays/displays.js.map +1 -1
  32. package/dist/filters/Filters.js +1 -1
  33. package/dist/filters/Filters.js.map +1 -1
  34. package/dist/filters/controls.js +1 -1
  35. package/dist/filters/controls.js.map +1 -1
  36. package/dist/filters/format.js.map +1 -1
  37. package/dist/index.d.ts +1 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -2
  40. package/dist/layouts/CardsLayout.js +1 -1
  41. package/dist/layouts/CardsLayout.js.map +1 -1
  42. package/dist/layouts/ItemTitle.js +20 -7
  43. package/dist/layouts/ItemTitle.js.map +1 -1
  44. package/dist/layouts/TableLayout.js +1 -1
  45. package/dist/layouts/TableLayout.js.map +1 -1
  46. package/dist/layouts/builtIn.js.map +1 -1
  47. package/dist/plugin.js.map +1 -1
  48. package/dist/query.js.map +1 -1
  49. package/dist/selection.js.map +1 -1
  50. package/dist/toolbar/LayoutSwitch.js +1 -1
  51. package/dist/toolbar/LayoutSwitch.js.map +1 -1
  52. package/dist/toolbar/Pagination.js +152 -41
  53. package/dist/toolbar/Pagination.js.map +1 -1
  54. package/dist/toolbar/SearchField.js +1 -1
  55. package/dist/toolbar/SearchField.js.map +1 -1
  56. package/dist/toolbar/SortSelect.js +1 -1
  57. package/dist/toolbar/SortSelect.js.map +1 -1
  58. package/dist/useDraft.js.map +1 -1
  59. package/dist/useListState.js.map +1 -1
  60. package/dist/useRenderValue.js +1 -1
  61. package/dist/useRenderValue.js.map +1 -1
  62. package/dist/values.js.map +1 -1
  63. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"Filters.js","names":["filter","value","X","onClearSearch","text","label","id","onClear","_c","styles","_Fragment"],"sources":["../../src/filters/Filters.tsx"],"sourcesContent":["import { X } from 'lucide-react';\nimport { useState } from 'react';\n\nimport type { Field, Filter, FilterValue } from '@panneau/protocol';\nimport { Button, IconButton, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { FilterEntry, ListColumn } from '../types';\nimport styles from './Filters.module.css';\nimport { builtInFilters } from './controls';\nimport { formatFilterValue, getFilterLabel, getFilterOptions } from './format';\n\n/** Labels of filter values (relation ids), by filter id, for the chips. */\nexport type FilterLabels = Readonly<Record<string, Readonly<Record<string, string>>>>;\n\n/** Remembers the labels of filter values, for the chips of active filters. */\nexport function useFilterLabels(): {\n labels: FilterLabels;\n remember: (filter: string, value: string, label: string) => void;\n} {\n const [labels, setLabels] = useState<FilterLabels>({});\n return {\n labels,\n remember: (filter, value, label) =>\n setLabels((current) =>\n current[filter]?.[value] === label\n ? current\n : { ...current, [filter]: { ...current[filter], [value]: label } },\n ),\n };\n}\n\ninterface FilterContext {\n columns: readonly ListColumn[];\n fields: readonly Field[];\n labels: FilterLabels;\n}\n\nexport interface FilterControlsProps extends FilterContext {\n filters: readonly Filter[];\n /** The current filter values, by filter id. */\n values: Readonly<Record<string, FilterValue>>;\n onChange: (id: string, value: FilterValue | undefined) => void;\n onLabel: (filter: string, value: string, label: string) => void;\n /** Controls by filter type, over the built-in ones. */\n controls?: Readonly<Record<string, FilterEntry>> | undefined;\n}\n\n/** A control for each filter of the list. */\nexport function FilterControls({\n filters,\n values,\n onChange,\n onLabel,\n controls,\n columns,\n fields,\n labels,\n}: FilterControlsProps) {\n const intl = usePanneauIntl();\n return (\n <div\n role=\"group\"\n aria-label={intl.formatMessage(messages.filters)}\n className={styles.filters}\n >\n {filters.map((filter) => {\n const Control =\n controls?.[filter.type] ?? builtInFilters[filter.type] ?? builtInFilters.text;\n if (Control === undefined) {\n return null;\n }\n return (\n <Control\n key={filter.id}\n filter={filter}\n label={getFilterLabel(filter, columns, fields)}\n options={getFilterOptions(filter, columns, fields)}\n value={values[filter.id]}\n onChange={(value) => onChange(filter.id, value)}\n onLabel={(value, label) => onLabel(filter.id, value, label)}\n getValueLabel={(value) => labels[filter.id]?.[value] ?? null}\n />\n );\n })}\n </div>\n );\n}\n\nexport interface FilterChipsProps extends FilterContext {\n filters: readonly Filter[];\n values: Readonly<Record<string, FilterValue>>;\n /** The search, shown as a chip too. */\n q?: string | undefined;\n onRemove: (id: string) => void;\n onClearSearch: () => void;\n onClear: () => void;\n}\n\n/** The active filters and the search, as chips that remove them, and a button to clear them all. */\nexport function FilterChips({\n filters,\n values,\n q,\n onRemove,\n onClearSearch,\n onClear,\n columns,\n fields,\n labels,\n}: FilterChipsProps) {\n const intl = usePanneauIntl();\n const chips = Object.entries(values).map(([id, value]) => {\n const filter = filters.find((candidate) => candidate.id === id) ?? { id, type: 'text' };\n const label = getFilterLabel(filter, columns, fields);\n const text =\n filter.type === 'toggle'\n ? null\n : formatFilterValue(filter, value, {\n intl,\n options: getFilterOptions(filter, columns, fields),\n getValueLabel: (entry) => labels[id]?.[entry] ?? null,\n });\n return { id, label, text };\n });\n const search = q !== undefined && q !== '' ? q : null;\n if (chips.length === 0 && search === null) {\n return null;\n }\n return (\n <div className={styles.chips}>\n <ul aria-label={intl.formatMessage(messages.activeFilters)} className={styles.chips}>\n {search !== null ? (\n <li className={styles.chip}>\n <span className={styles.chipText}>\n {intl.formatMessage(messages.searchChip, { q: search })}\n </span>\n <IconButton\n icon={X}\n size=\"sm\"\n showTooltip={false}\n label={intl.formatMessage(messages.removeFilter, {\n filter: intl.formatMessage(messages.searchChip, { q: search }),\n })}\n onPress={onClearSearch}\n />\n </li>\n ) : null}\n {chips.map(({ id, label, text }) => {\n const name = text !== null ? `${label}: ${text}` : label;\n return (\n <li key={id} className={styles.chip}>\n <span className={styles.chipText}>\n {text !== null ? (\n <>\n <span className={styles.chipLabel}>{label}:</span> {text}\n </>\n ) : (\n label\n )}\n </span>\n <IconButton\n icon={X}\n size=\"sm\"\n showTooltip={false}\n label={intl.formatMessage(messages.removeFilter, { filter: name })}\n onPress={() => onRemove(id)}\n />\n </li>\n );\n })}\n </ul>\n <Button variant=\"ghost\" size=\"sm\" onPress={onClear}>\n {intl.formatMessage(messages.clearFilters)}\n </Button>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Filters.js","names":["X","useState","Field","Filter","FilterValue","Button","IconButton","usePanneauIntl","messages","FilterEntry","ListColumn","styles","builtInFilters","formatFilterValue","getFilterLabel","getFilterOptions","FilterLabels","Readonly","Record","useFilterLabels","$","_c","t0","Symbol","for","labels","setLabels","t1","filter","value","label","current","t2","remember","FilterContext","columns","fields","FilterControlsProps","filters","values","onChange","id","onLabel","controls","FilterControls","intl","formatMessage","t3","Control","type","text","undefined","value_0","value_1","map","FilterChipsProps","q","onRemove","onClearSearch","onClear","FilterChips","Object","entries","find","candidate","options","getValueLabel","entry","chips","search","length","activeFilters","chip","chipText","searchChip","removeFilter","t4","t5","id_0","label_0","text_0","name","chipLabel","t6","clearFilters","t7","t8","_c","styles","_Fragment"],"sources":["../../src/filters/Filters.tsx"],"sourcesContent":["import { X } from 'lucide-react';\nimport { useState } from 'react';\n\nimport type { Field, Filter, FilterValue } from '@panneau/protocol';\nimport { Button, IconButton, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { FilterEntry, ListColumn } from '../types';\nimport styles from './Filters.module.css';\nimport { builtInFilters } from './controls';\nimport { formatFilterValue, getFilterLabel, getFilterOptions } from './format';\n\n/** Labels of filter values (relation ids), by filter id, for the chips. */\nexport type FilterLabels = Readonly<Record<string, Readonly<Record<string, string>>>>;\n\n/** Remembers the labels of filter values, for the chips of active filters. */\nexport function useFilterLabels(): {\n labels: FilterLabels;\n remember: (filter: string, value: string, label: string) => void;\n} {\n const [labels, setLabels] = useState<FilterLabels>({});\n return {\n labels,\n remember: (filter, value, label) =>\n setLabels((current) =>\n current[filter]?.[value] === label\n ? current\n : { ...current, [filter]: { ...current[filter], [value]: label } },\n ),\n };\n}\n\ninterface FilterContext {\n columns: readonly ListColumn[];\n fields: readonly Field[];\n labels: FilterLabels;\n}\n\nexport interface FilterControlsProps extends FilterContext {\n filters: readonly Filter[];\n /** The current filter values, by filter id. */\n values: Readonly<Record<string, FilterValue>>;\n onChange: (id: string, value: FilterValue | undefined) => void;\n onLabel: (filter: string, value: string, label: string) => void;\n /** Controls by filter type, over the built-in ones. */\n controls?: Readonly<Record<string, FilterEntry>> | undefined;\n}\n\n/** A control for each filter of the list. */\nexport function FilterControls({\n filters,\n values,\n onChange,\n onLabel,\n controls,\n columns,\n fields,\n labels,\n}: FilterControlsProps) {\n const intl = usePanneauIntl();\n return (\n <div\n role=\"group\"\n aria-label={intl.formatMessage(messages.filters)}\n className={styles.filters}\n >\n {filters.map((filter) => {\n const Control =\n controls?.[filter.type] ?? builtInFilters[filter.type] ?? builtInFilters.text;\n if (Control === undefined) {\n return null;\n }\n return (\n <Control\n key={filter.id}\n filter={filter}\n label={getFilterLabel(filter, columns, fields)}\n options={getFilterOptions(filter, columns, fields)}\n value={values[filter.id]}\n onChange={(value) => onChange(filter.id, value)}\n onLabel={(value, label) => onLabel(filter.id, value, label)}\n getValueLabel={(value) => labels[filter.id]?.[value] ?? null}\n />\n );\n })}\n </div>\n );\n}\n\nexport interface FilterChipsProps extends FilterContext {\n filters: readonly Filter[];\n values: Readonly<Record<string, FilterValue>>;\n /** The search, shown as a chip too. */\n q?: string | undefined;\n onRemove: (id: string) => void;\n onClearSearch: () => void;\n onClear: () => void;\n}\n\n/** The active filters and the search, as chips that remove them, and a button to clear them all. */\nexport function FilterChips({\n filters,\n values,\n q,\n onRemove,\n onClearSearch,\n onClear,\n columns,\n fields,\n labels,\n}: FilterChipsProps) {\n const intl = usePanneauIntl();\n const chips = Object.entries(values).map(([id, value]) => {\n const filter = filters.find((candidate) => candidate.id === id) ?? { id, type: 'text' };\n const label = getFilterLabel(filter, columns, fields);\n const text =\n filter.type === 'toggle'\n ? null\n : formatFilterValue(filter, value, {\n intl,\n options: getFilterOptions(filter, columns, fields),\n getValueLabel: (entry) => labels[id]?.[entry] ?? null,\n });\n return { id, label, text };\n });\n const search = q !== undefined && q !== '' ? q : null;\n if (chips.length === 0 && search === null) {\n return null;\n }\n return (\n <div className={styles.chips}>\n <ul aria-label={intl.formatMessage(messages.activeFilters)} className={styles.chips}>\n {search !== null ? (\n <li className={styles.chip}>\n <span className={styles.chipText}>\n {intl.formatMessage(messages.searchChip, { q: search })}\n </span>\n <IconButton\n icon={X}\n size=\"sm\"\n showTooltip={false}\n label={intl.formatMessage(messages.removeFilter, {\n filter: intl.formatMessage(messages.searchChip, { q: search }),\n })}\n onPress={onClearSearch}\n />\n </li>\n ) : null}\n {chips.map(({ id, label, text }) => {\n const name = text !== null ? `${label}: ${text}` : label;\n return (\n <li key={id} className={styles.chip}>\n <span className={styles.chipText}>\n {text !== null ? (\n <>\n <span className={styles.chipLabel}>{label}:</span> {text}\n </>\n ) : (\n label\n )}\n </span>\n <IconButton\n icon={X}\n size=\"sm\"\n showTooltip={false}\n label={intl.formatMessage(messages.removeFilter, { filter: name })}\n onPress={() => onRemove(id)}\n />\n </li>\n );\n })}\n </ul>\n <Button variant=\"ghost\" size=\"sm\" onPress={onClear}>\n {intl.formatMessage(messages.clearFilters)}\n </Button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAAOmB,kBAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,GAAA;EAIgDF,KAAA,CAAC;EAACF,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAArD,MAAA,CAAAK,QAAAC,aAA4BzB,SAAuBqB,EAAE;CAAE,IAAAK;CAAA,IAAAP,EAAA,OAAAG,OAAAC,IAAA,2BAAA,GAAA;EAGzCG,MAAAC,QAAAC,OAAAC,UACNJ,WAAUK,YACNA,QAAQH,OAAgB,GAANC,WAAWC,QAA7BC,UAAA;GAAA,GAEWA;IAAUH,SAAS;IAAA,GAAKG,QAAQH;KAAUC,QAAQC;GAAM;EAAE,CACzE;EAACV,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAAA,IAAAY;CAAA,IAAAZ,EAAA,OAAAK,QAAA;EAPFO,KAAA;GAAAP;GAAAQ,UAEON;EAMd;EAACP,EAAA,KAAAK;EAAAL,EAAA,KAAAY;CAAA,OAAAA,KAAAZ,EAAA;CAAA,OARMY;AAQN;;AAoBL,SAAOY,eAAAtB,IAAA;CAAA,MAAAF,IAAAC,EAAA,EAAA;CAAwB,MAAA,EAAAiB,SAAAC,QAAAC,UAAAE,SAAAC,UAAAR,SAAAC,QAAAX,WAAAH;CAU3B,MAAAuB,OAAatC,eAAe;CAAE,IAAAoB;CAAA,IAAAP,EAAA,OAAAyB,MAAA;EAIVlB,KAAAkB,KAAIC,cAAetC,SAAQ8B,OAAQ;EAAClB,EAAA,KAAAyB;EAAAzB,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAAA,IAAAY;CAAA,IAAAZ,EAAA,OAAAe,WAAAf,EAAA,OAAAuB,YAAAvB,EAAA,OAAAgB,UAAAhB,EAAA,OAAAkB,WAAAlB,EAAA,OAAAK,UAAAL,EAAA,OAAAoB,YAAApB,EAAA,OAAAsB,WAAAtB,EAAA,OAAAmB,QAAA;EAAA,IAAAQ;EAAA,IAAA3B,EAAA,QAAAe,WAAAf,EAAA,QAAAuB,YAAAvB,EAAA,QAAAgB,UAAAhB,EAAA,QAAAK,UAAAL,EAAA,QAAAoB,YAAApB,EAAA,QAAAsB,WAAAtB,EAAA,QAAAmB,QAAA;GAGnCQ,MAAAnB,WAAA;IACT,MAAAoB,UACIL,WAAWf,OAAMqB,SAAUrC,eAAegB,OAAMqB,SAAUrC,eAAcsC;IAC5E,IAAIF,YAAYG,KAAAA,GAAS,OACd;IACV,OAEG,oBAAC,SAAD;KAEYvB;KACD,OAAAd,eAAec,QAAQO,SAASC,MAAM;KACpC,SAAArB,iBAAiBa,QAAQO,SAASC,MAAM;KAC1C,OAAAG,OAAOX,OAAMa;KACV,WAAAZ,UAAWW,SAASZ,OAAMa,IAAKZ,KAAK;KACrC,UAAAuB,SAAAtB,UAAkBY,QAAQd,OAAMa,IAAKZ,SAAOC,KAAK;KAC3C,gBAAAuB,YAAW5B,OAAOG,OAAMa,GAAa,GAANZ,YAApB;IAAkC,GAPvDD,OAAMa,EAOiD;GAC9D;GAETrB,EAAA,MAAAe;GAAAf,EAAA,MAAAuB;GAAAvB,EAAA,MAAAgB;GAAAhB,EAAA,MAAAK;GAAAL,EAAA,MAAAoB;GAAApB,EAAA,MAAAsB;GAAAtB,EAAA,MAAAmB;GAAAnB,EAAA,MAAA2B;EAAA,OAAAA,KAAA3B,EAAA;EAlBAY,KAAAM,QAAOgB,IAAKP,EAkBZ;EAAC3B,EAAA,KAAAe;EAAAf,EAAA,KAAAuB;EAAAvB,EAAA,KAAAgB;EAAAhB,EAAA,KAAAkB;EAAAlB,EAAA,KAAAK;EAAAL,EAAA,KAAAoB;EAAApB,EAAA,KAAAsB;EAAAtB,EAAA,KAAAmB;EAAAnB,EAAA,MAAAY;CAAA,OAAAA,KAAAZ,EAAA;CAAA,IAAA2B;CAAA,IAAA3B,EAAA,QAAAO,MAAAP,EAAA,QAAAY,IAAA;EAvBNe,KAAA,oBAAA,OAAA;GACS,MAAA;GACO,cAAApB;GACD,WAAAhB,uBAAM2B;GAEhBN,UAAAA;EAmBC,CAAA;EAAAZ,EAAA,MAAAO;EAAAP,EAAA,MAAAY;EAAAZ,EAAA,MAAA2B;CAAA,OAAAA,KAAA3B,EAAA;CAAA,OAxBN2B;AAwBM;;AAed,SAAOa,YAAAtC,IAAA;CAAA,MAAAF,IAAAC,EAAA,EAAA;CAAqB,MAAA,EAAAiB,SAAAC,QAAAiB,GAAAC,UAAAC,eAAAC,SAAAxB,SAAAC,QAAAX,WAAAH;CAWxB,MAAAuB,OAAatC,eAAe;CAAE,IAAAoB;CAAA,IAAAP,EAAA,OAAAe,WAAAf,EAAA,OAAAgB,UAAAhB,EAAA,OAAAkB,WAAAlB,EAAA,OAAAyB,QAAAzB,EAAA,OAAAK,UAAAL,EAAA,OAAAmB,QAAA;EAChBZ,KAAAkC,OAAMC,QAASvB,MAAM,CAAC,CAAAe,KAAKtB,OAAA;GAAC,MAAA,CAAAS,IAAAZ,SAAAG;GACtC,MAAAJ,SAAeU,QAAOyB,MAAMC,cAAeA,UAASvB,OAAQA,EAA0B,KAAvE;IAAAA;IAAAQ,MAAgE;GAAO;GASzE,OACN;IAAAR;IAAAX,OATOhB,eAAec,QAAQO,SAASC,MASvCN;IAAAoB,MAPHtB,OAAMqB,SAAU,WAAhB,OAEMpC,kBAAkBe,QAAQC,OAAO;KAAAgB;KAAAoB,SAEpBlD,iBAAiBa,QAAQO,SAASC,MAAM;KAAC8B,gBACnCC,UAAW1C,OAAOgB,GAAY,GAAN0B,UAAb;IAC9B,CAAC;GACc;EAAC,CAC7B;EAAC/C,EAAA,KAAAe;EAAAf,EAAA,KAAAgB;EAAAhB,EAAA,KAAAkB;EAAAlB,EAAA,KAAAyB;EAAAzB,EAAA,KAAAK;EAAAL,EAAA,KAAAmB;EAAAnB,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAZF,MAAAgD,QAAczC;CAad,MAAA0C,SAAeb,MAAML,KAAAA,KAAaK,MAAM,KAAzBA,IAAA;CACf,IAAIY,MAAKE,WAAY,KAAKD,WAAW,MAAI,OAC9B;CACV,IAAArC;CAAA,IAAAZ,EAAA,OAAAyB,MAAA;EAGuBb,KAAAa,KAAIC,cAAetC,SAAQ+D,aAAc;EAACnD,EAAA,KAAAyB;EAAAzB,EAAA,KAAAY;CAAA,OAAAA,KAAAZ,EAAA;CAAA,IAAA2B;CAAA,IAAA3B,EAAA,OAAAyB,QAAAzB,EAAA,QAAAsC,iBAAAtC,EAAA,QAAAiD,QAAA;EACrDtB,KAAAsB,WAAW,OACR,qBAAA,MAAA;GAAe,WAAA1D,uBAAM6D;GAArB,UAAA,CACI,oBAAA,QAAA;IAAiB,WAAA7D,uBAAM8D;IAClB5B,UAAAA,KAAIC,cAAetC,SAAQkE,YAAa,EAAAlB,GAAKa,OAAO,CAAC;GACnD,CAAA,GACP,oBAAC,YAAD;IACUrE,MAAAA;IACD,MAAA;IACQ,aAAA;IACN,OAAA6C,KAAIC,cAAetC,SAAQmE,cAAe,EAAA/C,QACrCiB,KAAIC,cAAetC,SAAQkE,YAAa,EAAAlB,GAAKa,OAAO,CAAC,EACjE,CAAC;IACQX,SAAAA;GAAa,CAAA,CAEzB;EAdR,CAAA,IAAA;EAeOtC,EAAA,KAAAyB;EAAAzB,EAAA,MAAAsC;EAAAtC,EAAA,MAAAiD;EAAAjD,EAAA,MAAA2B;CAAA,OAAAA,KAAA3B,EAAA;CAAA,IAAAwD;CAAA,IAAAxD,EAAA,QAAAgD,SAAAhD,EAAA,QAAAyB,QAAAzB,EAAA,QAAAqC,UAAA;EACPmB,KAAAR,MAAKd,KAAKuB,OAAA;GAAC,MAAA,EAAApC,IAAAqC,MAAAhD,OAAAiD,SAAA7B,MAAA8B,WAAAH;GACR,MAAAI,OAAa/B,WAAS,OAAT,GAAmBpB,QAAK,IAAKoB,WAA7B6B;GAA4C,OAErD,qBAAA,MAAA;IAAwB,WAAApE,uBAAM6D;IAA9B,UAAA,CACI,oBAAA,QAAA;KAAiB,WAAA7D,uBAAM8D;KAClBvB,UAAAA,WAAS,OAAT,qBAAAuC,UAAA,EAAA,UAAA;MAEO,qBAAA,QAAA;OAAiB,WAAA9E,uBAAMuE;OAAvB,UAAA,CAAoCpD,SAAM,GAAQ;;MAAA;MAAEoB;KAAI,EAAA,CAAA,IAF/D6B;IAOE,CAAA,GACP,oBAAC,YAAD;KACU/E,MAAAA;KACD,MAAA;KACQ,aAAA;KACN,OAAA6C,KAAIC,cAAetC,SAAQmE,cAAe,EAAA/C,QAAUqD,KAAK,CAAC;KACxD,eAAMxB,SAAShB,IAAE;IAAC,CAAA,CAE9B;GAjBIA,GAAAA,IAiBJ;EAAA,CAEZ;EAACrB,EAAA,MAAAgD;EAAAhD,EAAA,MAAAyB;EAAAzB,EAAA,MAAAqC;EAAArC,EAAA,MAAAwD;CAAA,OAAAA,KAAAxD,EAAA;CAAA,IAAAyD;CAAA,IAAAzD,EAAA,QAAAY,MAAAZ,EAAA,QAAA2B,MAAA3B,EAAA,QAAAwD,IAAA;EAvCNC,KAAA,qBAAA,MAAA;GAAgB,cAAA7C;GAAuD,WAAArB,uBAAMyD;GAA7E,UAAA,CACKrB,IAgBA6B,EAuBA;;EAAAxD,EAAA,MAAAY;EAAAZ,EAAA,MAAA2B;EAAA3B,EAAA,MAAAwD;EAAAxD,EAAA,MAAAyD;CAAA,OAAAA,KAAAzD,EAAA;CAAA,IAAA+D;CAAA,IAAA/D,EAAA,QAAAyB,MAAA;EAEAsC,KAAAtC,KAAIC,cAAetC,SAAQ4E,YAAa;EAAChE,EAAA,MAAAyB;EAAAzB,EAAA,MAAA+D;CAAA,OAAAA,KAAA/D,EAAA;CAAA,IAAAiE;CAAA,IAAAjE,EAAA,QAAAuC,WAAAvC,EAAA,QAAA+D,IAAA;EAD9CE,KAAA,oBAAC,QAAD;GAAgB,SAAA;GAAa,MAAA;GAAc1B,SAAAA;GACtCwB,UAAAA;EADE,CAAA;EAEE/D,EAAA,MAAAuC;EAAAvC,EAAA,MAAA+D;EAAA/D,EAAA,MAAAiE;CAAA,OAAAA,KAAAjE,EAAA;CAAA,IAAAkE;CAAA,IAAAlE,EAAA,QAAAyD,MAAAzD,EAAA,QAAAiE,IAAA;EA5CbC,KAAA,qBAAA,OAAA;GAAgB,WAAA3E,uBAAMyD;GAAtB,UAAA,CACIS,IAyCAQ,EAGE;;EAAAjE,EAAA,MAAAyD;EAAAzD,EAAA,MAAAiE;EAAAjE,EAAA,MAAAkE;CAAA,OAAAA,KAAAlE,EAAA;CAAA,OA7CNkE;AA6CM"}
@@ -1,9 +1,9 @@
1
1
  import { messages } from "../messages.js";
2
2
  import { useDraft } from "../useDraft.js";
3
3
  import Filters_module_default from "./Filters.module.js";
4
+ import { c } from "react/compiler-runtime";
4
5
  import { Fieldset, Select, Switch, TextInput, usePanneauIntl } from "@panneau/ui";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
- import { c } from "react/compiler-runtime";
7
7
  import { useFieldsContext } from "@panneau/fields";
8
8
  import { useEffect } from "react";
9
9
  import { DateField } from "@panneau/fields/date";
@@ -1 +1 @@
1
- {"version":3,"file":"controls.js","names":["label","draft","setDraft","flush","options","placeholder","option","reference","next","resource","references","_c","styles"],"sources":["../../src/filters/controls.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport { useFieldsContext } from '@panneau/fields';\nimport { DateField } from '@panneau/fields/date';\nimport { RelationField, useRelationReferences } from '@panneau/fields/relation';\nimport type { FilterValue } from '@panneau/protocol';\nimport { isFilterRange } from '@panneau/protocol/runtime';\nimport { Fieldset, type OptionValue, Select, Switch, TextInput, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { FilterControlProps, FilterEntry } from '../types';\nimport { useDraft } from '../useDraft';\nimport styles from './Filters.module.css';\n\nfunction asStrings(value: unknown): string[] {\n if (isFilterRange(value)) {\n return [];\n }\n if (Array.isArray(value)) {\n return value.map(String);\n }\n return value === undefined || value === null || value === '' ? [] : [String(value)];\n}\n\n/** A text filter: the list changes once the user stops typing. */\nexport function TextFilter({ label, value, onChange }: FilterControlProps) {\n const current = typeof value === 'string' || typeof value === 'number' ? String(value) : '';\n const { draft, setDraft, flush } = useDraft(current, (next) =>\n onChange(next !== '' ? next : undefined),\n );\n return (\n <TextInput\n label={label}\n value={draft}\n onChange={setDraft}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n flush();\n }\n }}\n onBlur={flush}\n className={styles.control}\n />\n );\n}\n\n/** A choice among the options, or several with `multiple`. */\nexport function SelectFilter({ filter, label, options, value, onChange }: FilterControlProps) {\n const intl = usePanneauIntl();\n const selected = asStrings(value);\n // Values from the URL are strings: match them to the options' values.\n const toOptions = (values: readonly string[]): OptionValue[] =>\n options\n .filter((option) => values.includes(String(option.value)))\n .map((option) => option.value);\n const placeholder = intl.formatMessage(messages.any);\n if (filter.multiple === true) {\n return (\n <Select\n multiple\n label={label}\n options={options}\n placeholder={placeholder}\n value={toOptions(selected)}\n onChange={(next) => onChange(next.length > 0 ? next : undefined)}\n className={styles.control}\n />\n );\n }\n return (\n <Select\n label={label}\n options={options}\n placeholder={placeholder}\n value={toOptions(selected)[0] ?? null}\n onChange={(next) => onChange(next ?? undefined)}\n className={styles.control}\n />\n );\n}\n\n/** On or off: on filters with `true`, off removes the filter. */\nexport function ToggleFilter({ label, value, onChange }: FilterControlProps) {\n return (\n <Switch\n isSelected={String(value) === 'true'}\n onChange={(checked) => onChange(checked ? true : undefined)}\n className={styles.toggle}\n >\n {label}\n </Switch>\n );\n}\n\n/** A day (`2026-10-15`). */\nexport function DateFilter({ label, value, onChange }: FilterControlProps) {\n return (\n <DateField\n label={label}\n value={typeof value === 'string' && value !== '' ? value : null}\n onChange={(next) => onChange(next ?? undefined)}\n className={styles.control}\n />\n );\n}\n\n/**\n * A range of days, sent as its bounds (`filter[published_at][from]=2026-01-01&…[to]=…`). Either end\n * can be open: it is left out.\n */\nexport function DateRangeFilter({ label, value, onChange }: FilterControlProps) {\n const intl = usePanneauIntl();\n const range = isFilterRange(value) ? value : {};\n const from = range.from !== undefined ? String(range.from) : '';\n const to = range.to !== undefined ? String(range.to) : '';\n const set = (nextFrom: string, nextTo: string) =>\n onChange(\n nextFrom === '' && nextTo === ''\n ? undefined\n : {\n ...(nextFrom !== '' ? { from: nextFrom } : {}),\n ...(nextTo !== '' ? { to: nextTo } : {}),\n },\n );\n return (\n <Fieldset legend={label} className={styles.range}>\n {/* One row, like the other filters: the legend names the range, and each end is named\n for assistive technologies only. */}\n <div className={styles.rangeInputs}>\n <DateField\n aria-label={intl.formatMessage(messages.from)}\n value={from !== '' ? from : null}\n onChange={(next) => set(next ?? '', to)}\n />\n <span className={styles.rangeDash} aria-hidden=\"true\">\n –\n </span>\n <DateField\n aria-label={intl.formatMessage(messages.to)}\n value={to !== '' ? to : null}\n onChange={(next) => set(from, next ?? '')}\n />\n </div>\n </Fieldset>\n );\n}\n\n/**\n * An item of another resource (`resource`), or several with `multiple`, picked with the relation\n * source of the fields context. The filter keeps their ids; their labels are remembered for the\n * chips.\n */\nexport function RelationFilter({\n filter,\n label,\n value,\n onChange,\n onLabel,\n getValueLabel,\n}: FilterControlProps) {\n const resource = filter.resource ?? filter.id;\n // Ids from the URL have no label: the relation source resolves them, for the picker and chips.\n const references = useRelationReferences(\n useFieldsContext().relationSource,\n resource,\n asStrings(value).map((id) => ({ id, label: getValueLabel(id) ?? id })),\n );\n const remember = (next: readonly { id: string; label: string }[]) =>\n next.forEach((reference) => onLabel(reference.id, reference.label));\n useEffect(() => {\n references\n .filter((reference) => reference.label !== reference.id)\n .forEach((reference) => onLabel(reference.id, reference.label));\n }, [references, onLabel]);\n if (filter.multiple === true) {\n return (\n <RelationField\n multiple\n label={label}\n resource={resource}\n value={references}\n onChange={(next) => {\n remember(next ?? []);\n const ids: FilterValue | undefined =\n next !== null && next.length > 0\n ? next.map((reference) => reference.id)\n : undefined;\n onChange(ids);\n }}\n className={styles.control}\n />\n );\n }\n return (\n <RelationField\n label={label}\n resource={resource}\n value={references[0] ?? null}\n onChange={(next) => {\n remember(next !== null ? [next] : []);\n onChange(next?.id);\n }}\n className={styles.control}\n />\n );\n}\n\n/** The built-in filter controls, by filter type. Unknown types are text filters. */\nexport const builtInFilters: Readonly<Record<string, FilterEntry>> = {\n text: TextFilter,\n select: SelectFilter,\n toggle: ToggleFilter,\n date: DateFilter,\n 'date-range': DateRangeFilter,\n relation: RelationFilter,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"controls.js","names":["useEffect","useFieldsContext","DateField","RelationField","useRelationReferences","FilterValue","isFilterRange","Fieldset","OptionValue","Select","Switch","TextInput","usePanneauIntl","messages","FilterControlProps","FilterEntry","useDraft","styles","asStrings","value","Array","isArray","map","String","undefined","TextFilter","t0","$","_c","label","onChange","current","t1","next","draft","setDraft","flush","t2","event","key","t3","control","SelectFilter","filter","options","intl","T0","t4","t5","multiple","Symbol","for","bb0","selected","t6","values","option","includes","_temp","toOptions","t7","formatMessage","any","placeholder","t8","length","next_0","option_0","ToggleFilter","checked","toggle","DateFilter","DateRangeFilter","range","from","to","nextFrom","nextTo","set","rangeDash","t9","t10","t11","t12","rangeInputs","t13","RelationFilter","onLabel","getValueLabel","resource","id","relationSource","references","forEach","reference","remember","_temp2","reference_1","ids","_temp3","next_1","reference_2","reference_0","builtInFilters","Readonly","Record","text","select","date","relation","_c","styles"],"sources":["../../src/filters/controls.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport { useFieldsContext } from '@panneau/fields';\nimport { DateField } from '@panneau/fields/date';\nimport { RelationField, useRelationReferences } from '@panneau/fields/relation';\nimport type { FilterValue } from '@panneau/protocol';\nimport { isFilterRange } from '@panneau/protocol/runtime';\nimport { Fieldset, type OptionValue, Select, Switch, TextInput, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { FilterControlProps, FilterEntry } from '../types';\nimport { useDraft } from '../useDraft';\nimport styles from './Filters.module.css';\n\nfunction asStrings(value: unknown): string[] {\n if (isFilterRange(value)) {\n return [];\n }\n if (Array.isArray(value)) {\n return value.map(String);\n }\n return value === undefined || value === null || value === '' ? [] : [String(value)];\n}\n\n/** A text filter: the list changes once the user stops typing. */\nexport function TextFilter({ label, value, onChange }: FilterControlProps) {\n const current = typeof value === 'string' || typeof value === 'number' ? String(value) : '';\n const { draft, setDraft, flush } = useDraft(current, (next) =>\n onChange(next !== '' ? next : undefined),\n );\n return (\n <TextInput\n label={label}\n value={draft}\n onChange={setDraft}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n flush();\n }\n }}\n onBlur={flush}\n className={styles.control}\n />\n );\n}\n\n/** A choice among the options, or several with `multiple`. */\nexport function SelectFilter({ filter, label, options, value, onChange }: FilterControlProps) {\n const intl = usePanneauIntl();\n const selected = asStrings(value);\n // Values from the URL are strings: match them to the options' values.\n const toOptions = (values: readonly string[]): OptionValue[] =>\n options\n .filter((option) => values.includes(String(option.value)))\n .map((option) => option.value);\n const placeholder = intl.formatMessage(messages.any);\n if (filter.multiple === true) {\n return (\n <Select\n multiple\n label={label}\n options={options}\n placeholder={placeholder}\n value={toOptions(selected)}\n onChange={(next) => onChange(next.length > 0 ? next : undefined)}\n className={styles.control}\n />\n );\n }\n return (\n <Select\n label={label}\n options={options}\n placeholder={placeholder}\n value={toOptions(selected)[0] ?? null}\n onChange={(next) => onChange(next ?? undefined)}\n className={styles.control}\n />\n );\n}\n\n/** On or off: on filters with `true`, off removes the filter. */\nexport function ToggleFilter({ label, value, onChange }: FilterControlProps) {\n return (\n <Switch\n isSelected={String(value) === 'true'}\n onChange={(checked) => onChange(checked ? true : undefined)}\n className={styles.toggle}\n >\n {label}\n </Switch>\n );\n}\n\n/** A day (`2026-10-15`). */\nexport function DateFilter({ label, value, onChange }: FilterControlProps) {\n return (\n <DateField\n label={label}\n value={typeof value === 'string' && value !== '' ? value : null}\n onChange={(next) => onChange(next ?? undefined)}\n className={styles.control}\n />\n );\n}\n\n/**\n * A range of days, sent as its bounds (`filter[published_at][from]=2026-01-01&…[to]=…`). Either end\n * can be open: it is left out.\n */\nexport function DateRangeFilter({ label, value, onChange }: FilterControlProps) {\n const intl = usePanneauIntl();\n const range = isFilterRange(value) ? value : {};\n const from = range.from !== undefined ? String(range.from) : '';\n const to = range.to !== undefined ? String(range.to) : '';\n const set = (nextFrom: string, nextTo: string) =>\n onChange(\n nextFrom === '' && nextTo === ''\n ? undefined\n : {\n ...(nextFrom !== '' ? { from: nextFrom } : {}),\n ...(nextTo !== '' ? { to: nextTo } : {}),\n },\n );\n return (\n <Fieldset legend={label} className={styles.range}>\n {/* One row, like the other filters: the legend names the range, and each end is named\n for assistive technologies only. */}\n <div className={styles.rangeInputs}>\n <DateField\n aria-label={intl.formatMessage(messages.from)}\n value={from !== '' ? from : null}\n onChange={(next) => set(next ?? '', to)}\n />\n <span className={styles.rangeDash} aria-hidden=\"true\">\n –\n </span>\n <DateField\n aria-label={intl.formatMessage(messages.to)}\n value={to !== '' ? to : null}\n onChange={(next) => set(from, next ?? '')}\n />\n </div>\n </Fieldset>\n );\n}\n\n/**\n * An item of another resource (`resource`), or several with `multiple`, picked with the relation\n * source of the fields context. The filter keeps their ids; their labels are remembered for the\n * chips.\n */\nexport function RelationFilter({\n filter,\n label,\n value,\n onChange,\n onLabel,\n getValueLabel,\n}: FilterControlProps) {\n const resource = filter.resource ?? filter.id;\n // Ids from the URL have no label: the relation source resolves them, for the picker and chips.\n const references = useRelationReferences(\n useFieldsContext().relationSource,\n resource,\n asStrings(value).map((id) => ({ id, label: getValueLabel(id) ?? id })),\n );\n const remember = (next: readonly { id: string; label: string }[]) =>\n next.forEach((reference) => onLabel(reference.id, reference.label));\n useEffect(() => {\n references\n .filter((reference) => reference.label !== reference.id)\n .forEach((reference) => onLabel(reference.id, reference.label));\n }, [references, onLabel]);\n if (filter.multiple === true) {\n return (\n <RelationField\n multiple\n label={label}\n resource={resource}\n value={references}\n onChange={(next) => {\n remember(next ?? []);\n const ids: FilterValue | undefined =\n next !== null && next.length > 0\n ? next.map((reference) => reference.id)\n : undefined;\n onChange(ids);\n }}\n className={styles.control}\n />\n );\n }\n return (\n <RelationField\n label={label}\n resource={resource}\n value={references[0] ?? null}\n onChange={(next) => {\n remember(next !== null ? [next] : []);\n onChange(next?.id);\n }}\n className={styles.control}\n />\n );\n}\n\n/** The built-in filter controls, by filter type. Unknown types are text filters. */\nexport const builtInFilters: Readonly<Record<string, FilterEntry>> = {\n text: TextFilter,\n select: SelectFilter,\n toggle: ToggleFilter,\n date: DateFilter,\n 'date-range': DateRangeFilter,\n relation: RelationFilter,\n};\n"],"mappings":";;;;;;;;;;;;AAcA,SAASkB,UAAUC,OAA0B;CACzC,IAAIb,cAAca,KAAK,GACnB,OAAO,CAAA;CAEX,IAAIC,MAAMC,QAAQF,KAAK,GACnB,OAAOA,MAAMG,IAAIC,MAAM;CAE3B,OAAOJ,UAAUK,KAAAA,KAAaL,UAAU,QAAQA,UAAU,KAAK,CAAA,IAAK,CAACI,OAAOJ,KAAK,CAAC;AACtF;;AAGA,SAAOM,WAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAoB,MAAA,EAAAC,OAAAV,OAAAW,aAAAJ;CACvB,MAAAK,UAAgB,OAAOZ,UAAU,YAAY,OAAOA,UAAU,WAAWI,OAAOJ,KAAU,IAA1E;CAA4E,IAAAa;CAAA,IAAAL,EAAA,OAAAG,UAAA;EACvCE,MAAAC,SACjDH,SAASG,SAAS,KAATA,OAAAT,KAAAA,CAA8B;EAACG,EAAA,KAAAG;EAAAH,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAD5C,MAAA,EAAAO,OAAAC,UAAAC,UAAmCpB,SAASe,SAASC,EAErD;CAAE,IAAAK;CAAA,IAAAV,EAAA,OAAAS,OAAA;EAMiBC,MAAAC,UAAA;GACP,IAAIA,MAAKC,QAAS,SACdH,MAAM;EACT;EACJT,EAAA,KAAAS;EAAAT,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,IAAAa;CAAA,IAAAb,EAAA,OAAAO,SAAAP,EAAA,OAAAS,SAAAT,EAAA,OAAAE,SAAAF,EAAA,OAAAQ,YAAAR,EAAA,OAAAU,IAAA;EARLG,KAAA,oBAAC,WAAD;GACWX;GACAK,OAAAA;GACGC,UAAAA;GACC,WAAAE;GAKHD,QAAAA;GACG,WAAAnB,uBAAMwB;EAAQ,CAAA;EAC3Bd,EAAA,KAAAO;EAAAP,EAAA,KAAAS;EAAAT,EAAA,KAAAE;EAAAF,EAAA,KAAAQ;EAAAR,EAAA,KAAAU;EAAAV,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CAAA,OAXFa;AAWE;;AAKV,SAAOE,aAAAhB,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAsB,MAAA,EAAAe,QAAAd,OAAAe,SAAAzB,OAAAW,aAAAJ;CACzB,MAAAmB,OAAajC,eAAe;CAAE,IAAAkC;CAAA,IAAAd;CAAA,IAAAK;CAAA,IAAAG;CAAA,IAAAO;CAAA,IAAAC;CAAA,IAAArB,EAAA,OAAAgB,OAAAM,YAAAtB,EAAA,OAAAkB,QAAAlB,EAAA,OAAAE,SAAAF,EAAA,OAAAG,YAAAH,EAAA,OAAAiB,WAAAjB,EAAA,OAAAR,OAAA;EAUtB6B,KAAAE,OAQEC,IARF,6BAQC;EAACC,KAAA;GAjBV,MAAAC,WAAiBnC,UAAUC,KAAK;GAAE,IAAAmC;GAAA,IAAA3B,EAAA,QAAAiB,SAAA;IAEhBU,MAAAC,WACdX,QAAOD,QACKa,WAAYD,OAAME,SAAUlC,OAAOiC,OAAMrC,KAAM,CAAC,CAAC,CAAC,CAAAG,IACrDoC,KAAwB;IAAC/B,EAAA,MAAAiB;IAAAjB,EAAA,MAAA2B;GAAA,OAAAA,KAAA3B,EAAA;GAHtC,MAAAgC,YAAkBL;GAGqB,IAAAM;GAAA,IAAAjC,EAAA,QAAAkB,MAAA;IACnBe,KAAAf,KAAIgB,cAAehD,SAAQiD,GAAI;IAACnC,EAAA,MAAAkB;IAAAlB,EAAA,MAAAiC;GAAA,OAAAA,KAAAjC,EAAA;GAApD,MAAAoC,cAAoBH;GACpB,IAAIjB,OAAMM,aAAc,MAAI;IAAA,IAAAe;IAAA,IAAArC,EAAA,QAAAG,UAAA;KAQNkC,MAAA/B,SAAUH,SAASG,KAAIgC,SAAU,IAAdhC,OAAAT,KAAAA,CAAkC;KAACG,EAAA,MAAAG;KAAAH,EAAA,MAAAqC;IAAA,OAAAA,KAAArC,EAAA;IANpEqB,KAAA,oBAAC,QAAD;KACI,UAAA;KACOnB;KACEe;KACImB;KACN,OAAAJ,UAAUN,QAAQ;KACf,UAAAW;KACC,WAAA/C,uBAAMwB;IAAQ,CAAA;IAP7B,MAAAW;GAQE;GAILN,KAAArC;GACUoB,KAAAA;GACEe,KAAAA;GACImB,KAAAA;GACNhB,KAAAY,UAAUN,QAAQ,CAAC,CAAA,MAAnB;EAA8B;EAAA1B,EAAA,KAAAgB,OAAAM;EAAAtB,EAAA,KAAAkB;EAAAlB,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAiB;EAAAjB,EAAA,KAAAR;EAAAQ,EAAA,KAAAmB;EAAAnB,EAAA,KAAAK;EAAAL,EAAA,KAAAU;EAAAV,EAAA,KAAAa;EAAAb,EAAA,MAAAoB;EAAApB,EAAA,MAAAqB;CAAA,OAAA;EAAAF,KAAAnB,EAAA;EAAAK,KAAAL,EAAA;EAAAU,KAAAV,EAAA;EAAAa,KAAAb,EAAA;EAAAoB,KAAApB,EAAA;EAAAqB,KAAArB,EAAA;CAAA;CAAA,IAAAqB,OAAAE,OAAAC,IAAA,6BAAA,GAAA,OAAAH;CAAA,IAAAM;CAAA,IAAA3B,EAAA,QAAAG,UAAA;EAC3BwB,MAAAY,WAAUpC,SAASoC,UAAA1C,KAAAA,CAAiB;EAACG,EAAA,MAAAG;EAAAH,EAAA,MAAA2B;CAAA,OAAAA,KAAA3B,EAAA;CAAA,IAAAiC;CAAA,IAAAjC,EAAA,QAAAmB,MAAAnB,EAAA,QAAAK,MAAAL,EAAA,QAAAU,MAAAV,EAAA,QAAAa,MAAAb,EAAA,QAAAoB,MAAApB,EAAA,QAAA2B,IAAA;EALnDM,KAAA,oBAAC,IAAD;GACW/B,OAAAA;GACEe,SAAAA;GACImB,aAAAA;GACN,OAAAhB;GACG,UAAAO;GACC,WAAArC,uBAAMwB;EAAQ,CAAA;EAC3Bd,EAAA,MAAAmB;EAAAnB,EAAA,MAAAK;EAAAL,EAAA,MAAAU;EAAAV,EAAA,MAAAa;EAAAb,EAAA,MAAAoB;EAAApB,EAAA,MAAA2B;EAAA3B,EAAA,MAAAiC;CAAA,OAAAA,KAAAjC,EAAA;CAAA,OAPFiC;AAOE;;AA9BH,SAAAF,MAAAS,UAAA;CAAA,OAOsBX,SAAMrC;AAAM;AA4BzC,SAAOiD,aAAA1C,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAsB,MAAA,EAAAC,OAAAV,OAAAW,aAAAJ;CAGL,MAAAM,KAAAT,OAAOJ,KAAK,MAAM;CAAM,IAAAkB;CAAA,IAAAV,EAAA,OAAAG,UAAA;EAC1BO,MAAAgC,YAAavC,SAASuC,UAAA,OAAA7C,KAAAA,CAA0B;EAACG,EAAA,KAAAG;EAAAH,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,IAAAa;CAAA,IAAAb,EAAA,OAAAE,SAAAF,EAAA,OAAAK,MAAAL,EAAA,OAAAU,IAAA;EAF/DG,KAAA,oBAAC,QAAD;GACgB,YAAAR;GACF,UAAAK;GACC,WAAApB,uBAAMqD;GAEhBzC,UAAAA;EALE,CAAA;EAMEF,EAAA,KAAAE;EAAAF,EAAA,KAAAK;EAAAL,EAAA,KAAAU;EAAAV,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CAAA,OANTa;AAMS;;AAKjB,SAAO+B,WAAA7C,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAoB,MAAA,EAAAC,OAAAV,OAAAW,aAAAJ;CAIR,MAAAM,KAAA,OAAOb,UAAU,YAAYA,UAAU,KAAvCA,QAAA;CAAwD,IAAAkB;CAAA,IAAAV,EAAA,OAAAG,UAAA;EACrDO,MAAAJ,SAAUH,SAASG,QAAAT,KAAAA,CAAiB;EAACG,EAAA,KAAAG;EAAAH,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,IAAAa;CAAA,IAAAb,EAAA,OAAAE,SAAAF,EAAA,OAAAK,MAAAL,EAAA,OAAAU,IAAA;EAHnDG,KAAA,oBAAC,WAAD;GACWX;GACA,OAAAG;GACG,UAAAK;GACC,WAAApB,uBAAMwB;EAAQ,CAAA;EAC3Bd,EAAA,KAAAE;EAAAF,EAAA,KAAAK;EAAAL,EAAA,KAAAU;EAAAV,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CAAA,OALFa;AAKE;;;;;AAQV,SAAOgC,gBAAA9C,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAyB,MAAA,EAAAC,OAAAV,OAAAW,aAAAJ;CAC5B,MAAAmB,OAAajC,eAAe;CAAE,IAAAoB;CAAA,IAAAL,EAAA,OAAAR,OAAA;EAChBa,KAAA1B,cAAca,KAAkB,IAAhCA,QAAA,CAAgC;EAACQ,EAAA,KAAAR;EAAAQ,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAA/C,MAAA8C,QAAczC;CACd,MAAA0C,OAAaD,MAAKC,SAAUlD,KAAAA,IAAYD,OAAOkD,MAAKC,IAAU,IAAjD;CACb,MAAAC,KAAWF,MAAKE,OAAQnD,KAAAA,IAAYD,OAAOkD,MAAKE,EAAQ,IAA7C;CAA+C,IAAAtC;CAAA,IAAAV,EAAA,OAAAG,UAAA;EAC9CO,MAAAuC,UAAAC,WACR/C,SACI8C,aAAa,MAAMC,WAAW,KAA9BrD,KAAAA,IAAA;GAAA,GAGcoD,aAAa,KAAb,EAAAF,MAA0BE,SAAc,IAAxC,CAAwC;GAAC,GACzCC,WAAW,KAAX,EAAAF,IAAsBE,OAAY,IAAlC,CAAkC;EAC1C,CACV;EAAClD,EAAA,KAAAG;EAAAH,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CARL,MAAAmD,MAAYzC;CAQN,IAAAG;CAAA,IAAAb,EAAA,OAAAkB,MAAA;EAOsBL,KAAAK,KAAIgB,cAAehD,SAAQ6D,IAAK;EAAC/C,EAAA,KAAAkB;EAAAlB,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CACtC,MAAAoB,KAAA2B,SAAS,KAATA,OAAA;CAAyB,IAAA1B;CAAA,IAAArB,EAAA,OAAAmD,OAAAnD,EAAA,OAAAgD,IAAA;EACtB3B,MAAAf,SAAU6C,IAAI7C,QAAA,IAAY0C,EAAE;EAAChD,EAAA,KAAAmD;EAAAnD,EAAA,KAAAgD;EAAAhD,EAAA,KAAAqB;CAAA,OAAAA,KAAArB,EAAA;CAAA,IAAA2B;CAAA,IAAA3B,EAAA,OAAAa,MAAAb,EAAA,QAAAoB,MAAApB,EAAA,QAAAqB,IAAA;EAH3CM,KAAA,oBAAC,WAAD;GACgB,cAAAd;GACL,OAAAO;GACG,UAAAC;EAA6B,CAAA;EACzCrB,EAAA,KAAAa;EAAAb,EAAA,MAAAoB;EAAApB,EAAA,MAAAqB;EAAArB,EAAA,MAAA2B;CAAA,OAAAA,KAAA3B,EAAA;CAAA,IAAAiC;CAAA,IAAAjC,EAAA,QAAAuB,OAAAC,IAAA,2BAAA,GAAA;EACFS,KAAA,oBAAA,QAAA;GAAiB,WAAA3C,uBAAM8D;GAAwB,eAAA;GAAO,UAAA;EAE/C,CAAA;EAAApD,EAAA,MAAAiC;CAAA,OAAAA,KAAAjC,EAAA;CAAA,IAAAqC;CAAA,IAAArC,EAAA,QAAAkB,MAAA;EAESmB,KAAAnB,KAAIgB,cAAehD,SAAQ8D,EAAG;EAAChD,EAAA,MAAAkB;EAAAlB,EAAA,MAAAqC;CAAA,OAAAA,KAAArC,EAAA;CACpC,MAAAqD,KAAAL,OAAO,KAAPA,KAAA;CAAqB,IAAAM;CAAA,IAAAtD,EAAA,QAAA+C,QAAA/C,EAAA,QAAAmD,KAAA;EAClBG,OAAAf,WAAUY,IAAIJ,MAAMR,UAAA,EAAU;EAACvC,EAAA,MAAA+C;EAAA/C,EAAA,MAAAmD;EAAAnD,EAAA,MAAAsD;CAAA,OAAAA,MAAAtD,EAAA;CAAA,IAAAuD;CAAA,IAAAvD,EAAA,QAAAsD,OAAAtD,EAAA,QAAAqC,MAAArC,EAAA,QAAAqD,IAAA;EAH7CE,MAAA,oBAAC,WAAD;GACgB,cAAAlB;GACL,OAAAgB;GACG,UAAAC;EAA+B,CAAA;EAC3CtD,EAAA,MAAAsD;EAAAtD,EAAA,MAAAqC;EAAArC,EAAA,MAAAqD;EAAArD,EAAA,MAAAuD;CAAA,OAAAA,MAAAvD,EAAA;CAAA,IAAAwD;CAAA,IAAAxD,EAAA,QAAAuD,OAAAvD,EAAA,QAAA2B,IAAA;EAbN6B,MAAA,qBAAA,OAAA;GAAgB,WAAAlE,uBAAMmE;GAAtB,UAAA;IACI9B;IAKAM;IAGAsB;GAKE;;EAAAvD,EAAA,MAAAuD;EAAAvD,EAAA,MAAA2B;EAAA3B,EAAA,MAAAwD;CAAA,OAAAA,MAAAxD,EAAA;CAAA,IAAA0D;CAAA,IAAA1D,EAAA,QAAAE,SAAAF,EAAA,QAAAwD,KAAA;EAjBVE,MAAA,oBAAC,UAAD;GAAkBxD,QAAAA;GAAkB,WAAAZ,uBAAMwD;GAGtCU,UAAAA;EAHK,CAAA;EAkBExD,EAAA,MAAAE;EAAAF,EAAA,MAAAwD;EAAAxD,EAAA,MAAA0D;CAAA,OAAAA,MAAA1D,EAAA;CAAA,OAlBX0D;AAkBW;;;;;;AASnB,SAAOC,eAAA5D,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAwB,MAAA,EAAAe,QAAAd,OAAAV,OAAAW,UAAAyD,SAAAC,kBAAA9D;CAQ3B,MAAA+D,WAAiB9C,OAAM8C,YAAa9C,OAAM+C;CAGtC,MAAA1D,KAAA/B,iBAAiB,CAAC,CAAA0F;CAAe,IAAAtD;CAAA,IAAAV,EAAA,OAAA6D,iBAAA7D,EAAA,OAAAR,OAAA;EAAA,IAAAqB;EAAA,IAAAb,EAAA,OAAA6D,eAAA;GAEZhD,MAAAkD,QAAS;IAAAA;IAAA7D,OAAa2D,cAAcE,EAAQ,KAAtBA;GAAwB;GAAE/D,EAAA,KAAA6D;GAAA7D,EAAA,KAAAa;EAAA,OAAAA,KAAAb,EAAA;EAArEU,KAAAnB,UAAUC,KAAK,CAAC,CAAAG,IAAKkB,EAAgD;EAACb,EAAA,KAAA6D;EAAA7D,EAAA,KAAAR;EAAAQ,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAH1E,MAAAiE,aAAmBxF,sBACf4B,IACAyD,UACApD,EACJ;CAAE,IAAAG;CAAA,IAAAb,EAAA,OAAA4D,SAAA;EACe/C,MAAAP,SACbA,KAAI4D,SAASC,cAAeP,QAAQO,UAASJ,IAAKI,UAASjE,KAAM,CAAC;EAACF,EAAA,KAAA4D;EAAA5D,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CADvE,MAAAoE,WAAiBvD;CACuD,IAAAO;CAAA,IAAAC;CAAA,IAAArB,EAAA,OAAA4D,WAAA5D,EAAA,OAAAiE,YAAA;EAC9D7C,WAAA;GACN6C,WAAUjD,OACEqD,MAA+C,CAAC,CAAAH,SAC/CI,gBAAeV,QAAQO,YAASJ,IAAKI,YAASjE,KAAM,CAAC;EAAC;EACpEmB,KAAA,CAAC4C,YAAYL,OAAO;EAAC5D,EAAA,KAAA4D;EAAA5D,EAAA,KAAAiE;EAAAjE,EAAA,KAAAoB;EAAApB,EAAA,MAAAqB;CAAA,OAAA;EAAAD,KAAApB,EAAA;EAAAqB,KAAArB,EAAA;CAAA;CAJxB3B,UAAU+C,IAIPC,EAAqB;CACxB,IAAIL,OAAMM,aAAc,MAAI;EAAA,IAAAK;EAAA,IAAA3B,EAAA,QAAAG,YAAAH,EAAA,QAAAoE,UAAA;GAONzC,MAAAY,WAAA;IACN6B,SAAS7B,UAAA,CAAA,CAAU;IACnB,MAAAgC,MACIjE,WAAS,QAAQA,OAAIgC,SAAU,IACzBhC,OAAIX,IAAK6E,MACD,IAFd3E,KAAAA;IAGJM,SAASoE,GAAG;GAAC;GAChBvE,EAAA,MAAAG;GAAAH,EAAA,MAAAoE;GAAApE,EAAA,MAAA2B;EAAA,OAAAA,KAAA3B,EAAA;EAAA,IAAAiC;EAAA,IAAAjC,EAAA,QAAAE,SAAAF,EAAA,QAAAiE,cAAAjE,EAAA,QAAA8D,YAAA9D,EAAA,QAAA2B,IAAA;GAZLM,KAAA,oBAAC,eAAD;IACI,UAAA;IACO/B;IACG4D;IACHG,OAAAA;IACG,UAAAtC;IAQC,WAAArC,uBAAMwB;GAAQ,CAAA;GAC3Bd,EAAA,MAAAE;GAAAF,EAAA,MAAAiE;GAAAjE,EAAA,MAAA8D;GAAA9D,EAAA,MAAA2B;GAAA3B,EAAA,MAAAiC;EAAA,OAAAA,KAAAjC,EAAA;EAAA,OAdFiC;CAcE;CAOK,MAAAN,KAAAsC,WAAU,MAAV;CAAqB,IAAAhC;CAAA,IAAAjC,EAAA,QAAAG,YAAAH,EAAA,QAAAoE,UAAA;EAClBnC,MAAAwC,WAAA;GACNL,SAAS9D,WAAS,OAAT,CAAiBA,MAAI,IAArB,CAAA,CAA2B;GACpCH,SAASG,QAAIyD,EAAI;EAAC;EACrB/D,EAAA,MAAAG;EAAAH,EAAA,MAAAoE;EAAApE,EAAA,MAAAiC;CAAA,OAAAA,KAAAjC,EAAA;CAAA,IAAAqC;CAAA,IAAArC,EAAA,QAAAE,SAAAF,EAAA,QAAA8D,YAAA9D,EAAA,QAAA2B,MAAA3B,EAAA,QAAAiC,IAAA;EAPLI,KAAA,oBAAC,eAAD;GACWnC;GACG4D;GACH,OAAAnC;GACG,UAAAM;GAIC,WAAA3C,uBAAMwB;EAAQ,CAAA;EAC3Bd,EAAA,MAAAE;EAAAF,EAAA,MAAA8D;EAAA9D,EAAA,MAAA2B;EAAA3B,EAAA,MAAAiC;EAAAjC,EAAA,MAAAqC;CAAA,OAAAA,KAAArC,EAAA;CAAA,OATFqC;AASE;;AAnDH,SAAAmC,OAAAE,aAAA;CAAA,OAiC+CP,YAASJ;AAAG;AAjC3D,SAAAM,OAAAM,aAAA;CAAA,OAmB4BR,YAASjE,UAAWiE,YAASJ;AAAG;AAqCnE,IAAaa,iBAAwD;CACjEG,MAAMjF;CACNkF,QAAQjE;CACR4B,QAAQF;CACRwC,MAAMrC;CACN,cAAcC;CACdqC,UAAUvB;AACd"}
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","names":[],"sources":["../../src/filters/format.ts"],"sourcesContent":["import type { IntlShape } from 'react-intl';\n\nimport type { Field, Filter, Option } from '@panneau/protocol';\nimport { isFilterRange } from '@panneau/protocol/runtime';\n\nimport { messages } from '../messages';\nimport type { ListColumn } from '../types';\nimport { getFieldOptions, getOptionLabel } from '../values';\n\n/** The label of a filter: its `label`, the label of its field, or its id. */\nexport function getFilterLabel(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): string {\n if (filter.label !== undefined) {\n return filter.label;\n }\n const field = findFilterField(filter, columns, fields);\n return field?.label ?? filter.id;\n}\n\n/** The field a filter filters, when a column or the list's fields have one with its id. */\nexport function findFilterField(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): Field | null {\n return (\n fields.find((field) => field.name === filter.id) ??\n columns.find((column) => column.field?.name === filter.id)?.field ??\n null\n );\n}\n\n/** The options of a filter: its own, or those of the field it filters. */\nexport function getFilterOptions(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): readonly Option[] {\n return filter.options ?? getFieldOptions(findFilterField(filter, columns, fields));\n}\n\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nfunction formatDay(value: string, intl: IntlShape): string {\n const match = DATE_ONLY.exec(value);\n if (match === null) {\n return value;\n }\n return intl.formatDate(new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])), {\n dateStyle: 'medium',\n });\n}\n\n/** The value of an active filter, as the text of its chip. */\nexport function formatFilterValue(\n filter: Filter,\n value: unknown,\n {\n intl,\n options,\n getValueLabel,\n }: {\n intl: IntlShape;\n options: readonly Option[];\n getValueLabel: (value: string) => string | null;\n },\n): string {\n const values: unknown[] = Array.isArray(value) ? value : [value];\n switch (filter.type) {\n case 'toggle':\n return intl.formatMessage(String(value) === 'true' ? messages.yes : messages.no);\n case 'date':\n return formatDay(String(value), intl);\n case 'date-range': {\n const range = isFilterRange(value) ? value : {};\n const from = range.from !== undefined ? String(range.from) : '';\n const to = range.to !== undefined ? String(range.to) : '';\n return intl.formatMessage(messages.dateRange, {\n from: from !== '' ? formatDay(from, intl) : '…',\n to: to !== '' ? formatDay(to, intl) : '…',\n });\n }\n case 'relation':\n return values.map((entry) => getValueLabel(String(entry)) ?? String(entry)).join(', ');\n default:\n return values\n .map((entry) => getOptionLabel(options, entry) ?? String(entry))\n .join(', ');\n }\n}\n"],"mappings":";;;;;AAUA,SAAgB,eACZ,QACA,SACA,QACM;CACN,IAAI,OAAO,UAAU,KAAA,GACjB,OAAO,OAAO;CAGlB,OADc,gBAAgB,QAAQ,SAAS,MACxC,CAAA,EAAO,SAAS,OAAO;AAClC;;AAGA,SAAgB,gBACZ,QACA,SACA,QACY;CACZ,OACI,OAAO,MAAM,UAAU,MAAM,SAAS,OAAO,EAAE,KAC/C,QAAQ,MAAM,WAAW,OAAO,OAAO,SAAS,OAAO,EAAE,CAAC,EAAE,SAC5D;AAER;;AAGA,SAAgB,iBACZ,QACA,SACA,QACiB;CACjB,OAAO,OAAO,WAAW,gBAAgB,gBAAgB,QAAQ,SAAS,MAAM,CAAC;AACrF;AAEA,IAAM,YAAY;AAElB,SAAS,UAAU,OAAe,MAAyB;CACvD,MAAM,QAAQ,UAAU,KAAK,KAAK;CAClC,IAAI,UAAU,MACV,OAAO;CAEX,OAAO,KAAK,WAAW,IAAI,KAAK,OAAO,MAAM,EAAE,GAAG,OAAO,MAAM,EAAE,IAAI,GAAG,OAAO,MAAM,EAAE,CAAC,GAAG,EACvF,WAAW,SACf,CAAC;AACL;;AAGA,SAAgB,kBACZ,QACA,OACA,EACI,MACA,SACA,iBAME;CACN,MAAM,SAAoB,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;CAC/D,QAAQ,OAAO,MAAf;EACI,KAAK,UACD,OAAO,KAAK,cAAc,OAAO,KAAK,MAAM,SAAS,SAAS,MAAM,SAAS,EAAE;EACnF,KAAK,QACD,OAAO,UAAU,OAAO,KAAK,GAAG,IAAI;EACxC,KAAK,cAAc;GACf,MAAM,QAAQ,cAAc,KAAK,IAAI,QAAQ,CAAC;GAC9C,MAAM,OAAO,MAAM,SAAS,KAAA,IAAY,OAAO,MAAM,IAAI,IAAI;GAC7D,MAAM,KAAK,MAAM,OAAO,KAAA,IAAY,OAAO,MAAM,EAAE,IAAI;GACvD,OAAO,KAAK,cAAc,SAAS,WAAW;IAC1C,MAAM,SAAS,KAAK,UAAU,MAAM,IAAI,IAAI;IAC5C,IAAI,OAAO,KAAK,UAAU,IAAI,IAAI,IAAI;GAC1C,CAAC;EACL;EACA,KAAK,YACD,OAAO,OAAO,KAAK,UAAU,cAAc,OAAO,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;EACzF,SACI,OAAO,OACF,KAAK,UAAU,eAAe,SAAS,KAAK,KAAK,OAAO,KAAK,CAAC,CAAC,CAC/D,KAAK,IAAI;CACtB;AACJ"}
1
+ {"version":3,"file":"format.js","names":["IntlShape","Field","Filter","Option","isFilterRange","messages","ListColumn","getFieldOptions","getOptionLabel","getFilterLabel","filter","columns","fields","label","undefined","field","findFilterField","id","find","name","column","getFilterOptions","options","DATE_ONLY","formatDay","value","intl","match","exec","formatDate","Date","Number","dateStyle","formatFilterValue","getValueLabel","values","Array","isArray","type","formatMessage","String","yes","no","range","from","to","dateRange","map","entry","join"],"sources":["../../src/filters/format.ts"],"sourcesContent":["import type { IntlShape } from 'react-intl';\n\nimport type { Field, Filter, Option } from '@panneau/protocol';\nimport { isFilterRange } from '@panneau/protocol/runtime';\n\nimport { messages } from '../messages';\nimport type { ListColumn } from '../types';\nimport { getFieldOptions, getOptionLabel } from '../values';\n\n/** The label of a filter: its `label`, the label of its field, or its id. */\nexport function getFilterLabel(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): string {\n if (filter.label !== undefined) {\n return filter.label;\n }\n const field = findFilterField(filter, columns, fields);\n return field?.label ?? filter.id;\n}\n\n/** The field a filter filters, when a column or the list's fields have one with its id. */\nexport function findFilterField(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): Field | null {\n return (\n fields.find((field) => field.name === filter.id) ??\n columns.find((column) => column.field?.name === filter.id)?.field ??\n null\n );\n}\n\n/** The options of a filter: its own, or those of the field it filters. */\nexport function getFilterOptions(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): readonly Option[] {\n return filter.options ?? getFieldOptions(findFilterField(filter, columns, fields));\n}\n\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nfunction formatDay(value: string, intl: IntlShape): string {\n const match = DATE_ONLY.exec(value);\n if (match === null) {\n return value;\n }\n return intl.formatDate(new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])), {\n dateStyle: 'medium',\n });\n}\n\n/** The value of an active filter, as the text of its chip. */\nexport function formatFilterValue(\n filter: Filter,\n value: unknown,\n {\n intl,\n options,\n getValueLabel,\n }: {\n intl: IntlShape;\n options: readonly Option[];\n getValueLabel: (value: string) => string | null;\n },\n): string {\n const values: unknown[] = Array.isArray(value) ? value : [value];\n switch (filter.type) {\n case 'toggle':\n return intl.formatMessage(String(value) === 'true' ? messages.yes : messages.no);\n case 'date':\n return formatDay(String(value), intl);\n case 'date-range': {\n const range = isFilterRange(value) ? value : {};\n const from = range.from !== undefined ? String(range.from) : '';\n const to = range.to !== undefined ? String(range.to) : '';\n return intl.formatMessage(messages.dateRange, {\n from: from !== '' ? formatDay(from, intl) : '…',\n to: to !== '' ? formatDay(to, intl) : '…',\n });\n }\n case 'relation':\n return values.map((entry) => getValueLabel(String(entry)) ?? String(entry)).join(', ');\n default:\n return values\n .map((entry) => getOptionLabel(options, entry) ?? String(entry))\n .join(', ');\n }\n}\n"],"mappings":";;;;;AAUA,SAAgBS,eACZC,QACAC,SACAC,QACM;CACN,IAAIF,OAAOG,UAAUC,KAAAA,GACjB,OAAOJ,OAAOG;CAGlB,OADcG,gBAAgBN,QAAQC,SAASC,MACxCG,CAAAA,EAAOF,SAASH,OAAOO;AAClC;;AAGA,SAAgBD,gBACZN,QACAC,SACAC,QACY;CACZ,OACIA,OAAOM,MAAMH,UAAUA,MAAMI,SAAST,OAAOO,EAAE,KAC/CN,QAAQO,MAAME,WAAWA,OAAOL,OAAOI,SAAST,OAAOO,EAAE,CAAC,EAAEF,SAC5D;AAER;;AAGA,SAAgBM,iBACZX,QACAC,SACAC,QACiB;CACjB,OAAOF,OAAOY,WAAWf,gBAAgBS,gBAAgBN,QAAQC,SAASC,MAAM,CAAC;AACrF;AAEA,IAAMW,YAAY;AAElB,SAASC,UAAUC,OAAeC,MAAyB;CACvD,MAAMC,QAAQJ,UAAUK,KAAKH,KAAK;CAClC,IAAIE,UAAU,MACV,OAAOF;CAEX,OAAOC,KAAKG,WAAW,IAAIC,KAAKC,OAAOJ,MAAM,EAAE,GAAGI,OAAOJ,MAAM,EAAE,IAAI,GAAGI,OAAOJ,MAAM,EAAE,CAAC,GAAG,EACvFK,WAAW,SACf,CAAC;AACL;;AAGA,SAAgBC,kBACZvB,QACAe,OACA,EACIC,MACAJ,SACAY,iBAME;CACN,MAAMC,SAAoBC,MAAMC,QAAQZ,KAAK,IAAIA,QAAQ,CAACA,KAAK;CAC/D,QAAQf,OAAO4B,MAAf;EACI,KAAK,UACD,OAAOZ,KAAKa,cAAcC,OAAOf,KAAK,MAAM,SAASpB,SAASoC,MAAMpC,SAASqC,EAAE;EACnF,KAAK,QACD,OAAOlB,UAAUgB,OAAOf,KAAK,GAAGC,IAAI;EACxC,KAAK,cAAc;GACf,MAAMiB,QAAQvC,cAAcqB,KAAK,IAAIA,QAAQ,CAAC;GAC9C,MAAMmB,OAAOD,MAAMC,SAAS9B,KAAAA,IAAY0B,OAAOG,MAAMC,IAAI,IAAI;GAC7D,MAAMC,KAAKF,MAAME,OAAO/B,KAAAA,IAAY0B,OAAOG,MAAME,EAAE,IAAI;GACvD,OAAOnB,KAAKa,cAAclC,SAASyC,WAAW;IAC1CF,MAAMA,SAAS,KAAKpB,UAAUoB,MAAMlB,IAAI,IAAI;IAC5CmB,IAAIA,OAAO,KAAKrB,UAAUqB,IAAInB,IAAI,IAAI;GAC1C,CAAC;EACL;EACA,KAAK,YACD,OAAOS,OAAOY,KAAKC,UAAUd,cAAcM,OAAOQ,KAAK,CAAC,KAAKR,OAAOQ,KAAK,CAAC,CAAC,CAACC,KAAK,IAAI;EACzF,SACI,OAAOd,OACFY,KAAKC,UAAUxC,eAAec,SAAS0B,KAAK,KAAKR,OAAOQ,KAAK,CAAC,CAAC,CAC/DC,KAAK,IAAI;CACtB;AACJ"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { type ListActions, getActionHref, groupListActions, isAllowedOn } from './actions/actions';
2
2
  export { ConfirmDialog, type ConfirmDialogProps, type ConfirmPreview, } from './actions/ConfirmDialog';
3
3
  export { type ActionIcons, getActionIcon } from './actions/icons';
4
- export { BooleanDisplay, ColorDisplay, DateDisplay, DateTimeDisplay, EmailDisplay, EmptyValue, MediaDisplay, NumberDisplay, RelationDisplay, RichTextDisplay, SelectDisplay, TextDisplay, TimeDisplay, UrlDisplay, builtInDisplays, } from './displays/displays';
4
+ export { BooleanDisplay, ColorDisplay, DateDisplay, DateTimeDisplay, DurationDisplay, EmailDisplay, EmbedDisplay, EmptyValue, JsonDisplay, LocationDisplay, MediaDisplay, NumberDisplay, RelationDisplay, RichTextDisplay, SelectDisplay, TagsDisplay, TelDisplay, TextDisplay, TimeDisplay, UrlDisplay, builtInDisplays, } from './displays/displays';
5
5
  export { DateFilter, DateRangeFilter, RelationFilter, SelectFilter, TextFilter, ToggleFilter, builtInFilters, } from './filters/controls';
6
6
  export { CardsLayout } from './layouts/CardsLayout';
7
7
  export { TableLayout } from './layouts/TableLayout';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,eAAe,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,UAAU,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,YAAY,EACR,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,eAAe,EACf,eAAe,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EACf,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,eAAe,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,UAAU,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,YAAY,EACR,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,eAAe,EACf,eAAe,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { getActionHref, groupListActions, isAllowedOn } from "./actions/actions.
2
2
  import { ConfirmDialog } from "./actions/ConfirmDialog.js";
3
3
  import { getActionIcon } from "./actions/icons.js";
4
4
  import { getLocalizedValue, toText } from "./values.js";
5
- import { BooleanDisplay, ColorDisplay, DateDisplay, DateTimeDisplay, EmailDisplay, EmptyValue, MediaDisplay, NumberDisplay, RelationDisplay, RichTextDisplay, SelectDisplay, TextDisplay, TimeDisplay, UrlDisplay, builtInDisplays } from "./displays/displays.js";
5
+ import { BooleanDisplay, ColorDisplay, DateDisplay, DateTimeDisplay, DurationDisplay, EmailDisplay, EmbedDisplay, EmptyValue, JsonDisplay, LocationDisplay, MediaDisplay, NumberDisplay, RelationDisplay, RichTextDisplay, SelectDisplay, TagsDisplay, TelDisplay, TextDisplay, TimeDisplay, UrlDisplay, builtInDisplays } from "./displays/displays.js";
6
6
  import { DateFilter, DateRangeFilter, RelationFilter, SelectFilter, TextFilter, ToggleFilter, builtInFilters } from "./filters/controls.js";
7
7
  import { CardsLayout } from "./layouts/CardsLayout.js";
8
8
  import { TableLayout } from "./layouts/TableLayout.js";
@@ -16,4 +16,4 @@ import { ListView } from "./ListView.js";
16
16
  import { applyListQuery } from "./query.js";
17
17
  import { List } from "./List.js";
18
18
  import { listsPlugin } from "./plugin.js";
19
- export { BooleanDisplay, CardsLayout, ColorDisplay, ConfirmDialog, DateDisplay, DateFilter, DateRangeFilter, DateTimeDisplay, EmailDisplay, EmptyValue, ItemDetails, List, ListView, MediaDisplay, NumberDisplay, Pagination, RelationDisplay, RelationFilter, RichTextDisplay, SearchField, SelectDisplay, SelectFilter, TableLayout, TextDisplay, TextFilter, TimeDisplay, ToggleFilter, UrlDisplay, applyListQuery, builtInDisplays, builtInFilters, builtInLayouts, countSelected, getActionHref, getActionIcon, getLocalizedValue, getPageSelection, groupListActions, isAllowedOn, isItemSelected, listsPlugin, toText, useListState };
19
+ export { BooleanDisplay, CardsLayout, ColorDisplay, ConfirmDialog, DateDisplay, DateFilter, DateRangeFilter, DateTimeDisplay, DurationDisplay, EmailDisplay, EmbedDisplay, EmptyValue, ItemDetails, JsonDisplay, List, ListView, LocationDisplay, MediaDisplay, NumberDisplay, Pagination, RelationDisplay, RelationFilter, RichTextDisplay, SearchField, SelectDisplay, SelectFilter, TableLayout, TagsDisplay, TelDisplay, TextDisplay, TextFilter, TimeDisplay, ToggleFilter, UrlDisplay, applyListQuery, builtInDisplays, builtInFilters, builtInLayouts, countSelected, getActionHref, getActionIcon, getLocalizedValue, getPageSelection, groupListActions, isAllowedOn, isItemSelected, listsPlugin, toText, useListState };
@@ -1,9 +1,9 @@
1
1
  import { messages } from "../messages.js";
2
2
  import CardsLayout_module_default from "./CardsLayout.module.js";
3
3
  import { ItemTitle } from "./ItemTitle.js";
4
+ import { c } from "react/compiler-runtime";
4
5
  import { Checkbox, usePanneauIntl } from "@panneau/ui";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
- import { c } from "react/compiler-runtime";
7
7
  //#region src/layouts/CardsLayout.tsx
8
8
  /** Items as cards: the first column is the title, the others are listed under it. */
9
9
  function CardsLayout(t0) {
@@ -1 +1 @@
1
- {"version":3,"file":"CardsLayout.js","names":["pageSelection","label","current","selected","actions","_c","styles"],"sources":["../../src/layouts/CardsLayout.tsx"],"sourcesContent":["import { Checkbox, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { ListLayoutProps } from '../types';\nimport styles from './CardsLayout.module.css';\nimport { ItemTitle } from './ItemTitle';\n\n/** Items as cards: the first column is the title, the others are listed under it. */\nexport function CardsLayout({\n items,\n columns,\n renderValue,\n getItemLabel,\n getItemHref,\n isCurrent,\n selectable,\n isSelected,\n onToggle,\n renderActions,\n label,\n pageSelection,\n}: ListLayoutProps) {\n const intl = usePanneauIntl();\n const [title, ...others] = columns;\n return (\n <div>\n {selectable ? <div className={styles.pageSelection}>{pageSelection}</div> : null}\n <ul className={styles.cards} aria-label={label}>\n {items.map((item) => {\n const selected = selectable && isSelected(item);\n const actions = renderActions(item);\n const current = isCurrent?.(item) ?? false;\n return (\n <li\n key={item.id}\n className={styles.card}\n data-selected={selected || undefined}\n data-current={current || undefined}\n >\n <div className={styles.header}>\n <div className={styles.title}>\n <ItemTitle href={getItemHref?.(item) ?? null} current={current}>\n {title !== undefined\n ? renderValue(item, title)\n : getItemLabel(item)}\n </ItemTitle>\n </div>\n {selectable ? (\n <Checkbox\n aria-label={intl.formatMessage(messages.selectItem, {\n item: getItemLabel(item),\n })}\n isSelected={selected}\n onChange={() => onToggle(item)}\n />\n ) : null}\n </div>\n {others.length > 0 ? (\n <dl className={styles.values}>\n {others.map((column) => (\n <div key={column.id} className={styles.value}>\n <dt>{column.label ?? column.id}</dt>\n <dd>{renderValue(item, column)}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {actions !== null ? (\n <div className={styles.actions}>{actions}</div>\n ) : null}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CardsLayout.js","names":["Checkbox","usePanneauIntl","messages","ListLayoutProps","styles","ItemTitle","CardsLayout","t0","$","_c","items","columns","renderValue","getItemLabel","getItemHref","isCurrent","selectable","isSelected","onToggle","renderActions","label","pageSelection","intl","t1","t2","t3","t4","title","others","cards","map","item","selected","actions","current","id","card","undefined","header","formatMessage","selectItem","length","values","column","value","t5","t6","_c","styles"],"sources":["../../src/layouts/CardsLayout.tsx"],"sourcesContent":["import { Checkbox, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { ListLayoutProps } from '../types';\nimport styles from './CardsLayout.module.css';\nimport { ItemTitle } from './ItemTitle';\n\n/** Items as cards: the first column is the title, the others are listed under it. */\nexport function CardsLayout({\n items,\n columns,\n renderValue,\n getItemLabel,\n getItemHref,\n isCurrent,\n selectable,\n isSelected,\n onToggle,\n renderActions,\n label,\n pageSelection,\n}: ListLayoutProps) {\n const intl = usePanneauIntl();\n const [title, ...others] = columns;\n return (\n <div>\n {selectable ? <div className={styles.pageSelection}>{pageSelection}</div> : null}\n <ul className={styles.cards} aria-label={label}>\n {items.map((item) => {\n const selected = selectable && isSelected(item);\n const actions = renderActions(item);\n const current = isCurrent?.(item) ?? false;\n return (\n <li\n key={item.id}\n className={styles.card}\n data-selected={selected || undefined}\n data-current={current || undefined}\n >\n <div className={styles.header}>\n <div className={styles.title}>\n <ItemTitle href={getItemHref?.(item) ?? null} current={current}>\n {title !== undefined\n ? renderValue(item, title)\n : getItemLabel(item)}\n </ItemTitle>\n </div>\n {selectable ? (\n <Checkbox\n aria-label={intl.formatMessage(messages.selectItem, {\n item: getItemLabel(item),\n })}\n isSelected={selected}\n onChange={() => onToggle(item)}\n />\n ) : null}\n </div>\n {others.length > 0 ? (\n <dl className={styles.values}>\n {others.map((column) => (\n <div key={column.id} className={styles.value}>\n <dt>{column.label ?? column.id}</dt>\n <dd>{renderValue(item, column)}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {actions !== null ? (\n <div className={styles.actions}>{actions}</div>\n ) : null}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import link_module_default from "./link.module.js";
2
+ import { c } from "react/compiler-runtime";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  import { Link } from "react-aria-components";
4
5
  //#region src/layouts/ItemTitle.tsx
@@ -6,14 +7,26 @@ import { Link } from "react-aria-components";
6
7
  * The title of an item, as a link to it when the list has one. Links go through React Aria, so an
7
8
  * app's `RouterProvider` handles them with its router.
8
9
  */
9
- function ItemTitle({ href, current = false, children }) {
10
+ function ItemTitle(t0) {
11
+ const $ = c(4);
12
+ const { href, current: t1, children } = t0;
13
+ const current = t1 === void 0 ? false : t1;
10
14
  if (href === null) return children;
11
- return /* @__PURE__ */ jsx(Link, {
12
- className: link_module_default.link,
13
- href,
14
- "aria-current": current ? "page" : void 0,
15
- children
16
- });
15
+ const t2 = current ? "page" : void 0;
16
+ let t3;
17
+ if ($[0] !== children || $[1] !== href || $[2] !== t2) {
18
+ t3 = /* @__PURE__ */ jsx(Link, {
19
+ className: link_module_default.link,
20
+ href,
21
+ "aria-current": t2,
22
+ children
23
+ });
24
+ $[0] = children;
25
+ $[1] = href;
26
+ $[2] = t2;
27
+ $[3] = t3;
28
+ } else t3 = $[3];
29
+ return t3;
17
30
  }
18
31
  //#endregion
19
32
  export { ItemTitle };
@@ -1 +1 @@
1
- {"version":3,"file":"ItemTitle.js","names":["styles"],"sources":["../../src/layouts/ItemTitle.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Link } from 'react-aria-components';\n\nimport styles from './link.module.css';\n\n/**\n * The title of an item, as a link to it when the list has one. Links go through React Aria, so an\n * app's `RouterProvider` handles them with its router.\n */\nexport function ItemTitle({\n href,\n current = false,\n children,\n}: {\n href: string | null;\n /** The item is the one shown next to the list: its link is the current page. */\n current?: boolean;\n children: ReactNode;\n}) {\n if (href === null) {\n return children;\n }\n return (\n <Link className={styles.link} href={href} aria-current={current ? 'page' : undefined}>\n {children}\n </Link>\n );\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,UAAU,EACtB,MACA,UAAU,OACV,YAMD;CACC,IAAI,SAAS,MACT,OAAO;CAEX,OACI,oBAAC,MAAD;EAAM,WAAWA,oBAAO;EAAY;EAAM,gBAAc,UAAU,SAAS,KAAA;EACtE;CACC,CAAA;AAEd"}
1
+ {"version":3,"file":"ItemTitle.js","names":["ReactNode","Link","styles","ItemTitle","t0","$","_c","href","current","t1","children","undefined","t2","t3","link","_c","styles"],"sources":["../../src/layouts/ItemTitle.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Link } from 'react-aria-components';\n\nimport styles from './link.module.css';\n\n/**\n * The title of an item, as a link to it when the list has one. Links go through React Aria, so an\n * app's `RouterProvider` handles them with its router.\n */\nexport function ItemTitle({\n href,\n current = false,\n children,\n}: {\n href: string | null;\n /** The item is the one shown next to the list: its link is the current page. */\n current?: boolean;\n children: ReactNode;\n}) {\n if (href === null) {\n return children;\n }\n return (\n <Link className={styles.link} href={href} aria-current={current ? 'page' : undefined}>\n {children}\n </Link>\n );\n}\n"],"mappings":";;;;;;;;;AASA,SAAOG,UAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAmB,MAAA,EAAAC,MAAAC,SAAAC,IAAAC,aAAAN;CAEtB,MAAAI,UAAAC,OAAAE,KAAAA,IAAA,QAAAF;CAQA,IAAIF,SAAS,MAAI,OACNG;CAGiD,MAAAE,KAAAJ,UAAA,SAAAG,KAAAA;CAA4B,IAAAE;CAAA,IAAAR,EAAA,OAAAK,YAAAL,EAAA,OAAAE,QAAAF,EAAA,OAAAO,IAAA;EAApFC,KAAA,oBAAC,MAAD;GAAiB,WAAAX,oBAAMY;GAAaP;GAAoB,gBAAAK;GACnDF;EADA,CAAA;EAEEL,EAAA,KAAAK;EAAAL,EAAA,KAAAE;EAAAF,EAAA,KAAAO;EAAAP,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,OAFPQ;AAEO"}
@@ -2,10 +2,10 @@ import { messages } from "../messages.js";
2
2
  import { ItemTitle } from "./ItemTitle.js";
3
3
  import { cx } from "../cx.js";
4
4
  import TableLayout_module_default from "./TableLayout.module.js";
5
+ import { c } from "react/compiler-runtime";
5
6
  import { Checkbox, Icon, usePanneauIntl } from "@panneau/ui";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-react";
8
- import { c } from "react/compiler-runtime";
9
9
  //#region src/layouts/TableLayout.tsx
10
10
  /** The sort direction of a column, from the first `sort` value. */
11
11
  function getSortDirection(sort, column) {
@@ -1 +1 @@
1
- {"version":3,"file":"TableLayout.js","names":["pageSelection","item","selected","column","href","current","label","styles","_c"],"sources":["../../src/layouts/TableLayout.tsx"],"sourcesContent":["import { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';\n\nimport { Checkbox, Icon, usePanneauIntl } from '@panneau/ui';\n\nimport { cx } from '../cx';\nimport { messages } from '../messages';\nimport type { ListColumn, ListLayoutProps } from '../types';\nimport { ItemTitle } from './ItemTitle';\nimport styles from './TableLayout.module.css';\n\n/** The sort direction of a column, from the first `sort` value. */\nexport function getSortDirection(\n sort: readonly string[],\n column: ListColumn,\n): 'ascending' | 'descending' | null {\n const first = sort[0];\n if (first === column.id) {\n return 'ascending';\n }\n return first === `-${column.id}` ? 'descending' : null;\n}\n\nfunction alignClass(column: ListColumn): string | undefined {\n if (column.align === 'center') {\n return styles.center;\n }\n return column.align === 'end' ? styles.end : undefined;\n}\n\n/**\n * Items as a table, with sortable column headers. On narrow lists (phones), each row turns into a\n * block that shows the label of each value.\n */\nexport function TableLayout({\n items,\n columns,\n renderValue,\n getItemLabel,\n getItemHref,\n isCurrent,\n selectable,\n isSelected,\n onToggle,\n renderActions,\n sort,\n onSort,\n label,\n pageSelection,\n}: ListLayoutProps) {\n const intl = usePanneauIntl();\n const actions = items.map((item) => renderActions(item));\n const hasActions = actions.some((node) => node !== null);\n return (\n <div className={styles.scroller}>\n <table className={styles.table} aria-label={label}>\n <thead>\n <tr>\n {selectable ? <th className={styles.check}>{pageSelection}</th> : null}\n {columns.map((column) => {\n const direction = getSortDirection(sort, column);\n return (\n <th\n key={column.id}\n scope=\"col\"\n className={alignClass(column)}\n style={\n column.width !== undefined\n ? { width: column.width }\n : undefined\n }\n aria-sort={\n column.sortable === true ? (direction ?? 'none') : undefined\n }\n >\n {column.sortable === true ? (\n <button\n type=\"button\"\n className={cx(\n styles.sort,\n direction !== null && styles.sorted,\n )}\n onClick={() => onSort(column)}\n >\n {column.label ?? column.id}\n <span className={styles.sortIcon}>\n <Icon\n icon={\n direction === 'ascending'\n ? ArrowUp\n : direction === 'descending'\n ? ArrowDown\n : ArrowUpDown\n }\n size=\"sm\"\n />\n </span>\n </button>\n ) : (\n (column.label ?? column.id)\n )}\n </th>\n );\n })}\n {hasActions ? (\n <th className={styles.actionsCell}>\n <span className={styles.visuallyHidden}>\n {intl.formatMessage(messages.actions)}\n </span>\n </th>\n ) : null}\n </tr>\n </thead>\n <tbody>\n {items.map((item, row) => {\n const selected = selectable && isSelected(item);\n const href = getItemHref?.(item) ?? null;\n const current = isCurrent?.(item) ?? false;\n return (\n <tr\n key={item.id}\n data-selected={selected || undefined}\n data-current={current || undefined}\n >\n {selectable ? (\n <td className={styles.check}>\n <Checkbox\n aria-label={intl.formatMessage(messages.selectItem, {\n item: getItemLabel(item),\n })}\n isSelected={selected}\n onChange={() => onToggle(item)}\n />\n </td>\n ) : null}\n {columns.map((column, index) => (\n <td\n key={column.id}\n className={cx(\n alignClass(column),\n index === 0 && styles.title,\n )}\n >\n <span className={styles.cellLabel}>\n {column.label ?? column.id}\n </span>\n <span>\n {index === 0 ? (\n <ItemTitle href={href} current={current}>\n {renderValue(item, column)}\n </ItemTitle>\n ) : (\n renderValue(item, column)\n )}\n </span>\n </td>\n ))}\n {hasActions ? (\n <td className={styles.actionsCell}>{actions[row]}</td>\n ) : null}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TableLayout.js","names":["ArrowDown","ArrowUp","ArrowUpDown","Checkbox","Icon","usePanneauIntl","cx","messages","ListColumn","ListLayoutProps","ItemTitle","styles","getSortDirection","sort","column","first","id","alignClass","align","center","end","undefined","TableLayout","t0","$","_c","items","columns","renderValue","getItemLabel","getItemHref","isCurrent","selectable","isSelected","onToggle","renderActions","onSort","label","pageSelection","intl","actions","t1","t2","item","map","some","_temp","hasActions","check","t3","t4","direction","width","sortable","sorted","sortIcon","actionsCell","visuallyHidden","formatMessage","t5","t6","t7","item_0","row","selected","href","current","selectItem","column_0","index","title","cellLabel","t8","scroller","table","node","styles","_c"],"sources":["../../src/layouts/TableLayout.tsx"],"sourcesContent":["import { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';\n\nimport { Checkbox, Icon, usePanneauIntl } from '@panneau/ui';\n\nimport { cx } from '../cx';\nimport { messages } from '../messages';\nimport type { ListColumn, ListLayoutProps } from '../types';\nimport { ItemTitle } from './ItemTitle';\nimport styles from './TableLayout.module.css';\n\n/** The sort direction of a column, from the first `sort` value. */\nexport function getSortDirection(\n sort: readonly string[],\n column: ListColumn,\n): 'ascending' | 'descending' | null {\n const first = sort[0];\n if (first === column.id) {\n return 'ascending';\n }\n return first === `-${column.id}` ? 'descending' : null;\n}\n\nfunction alignClass(column: ListColumn): string | undefined {\n if (column.align === 'center') {\n return styles.center;\n }\n return column.align === 'end' ? styles.end : undefined;\n}\n\n/**\n * Items as a table, with sortable column headers. On narrow lists (phones), each row turns into a\n * block that shows the label of each value.\n */\nexport function TableLayout({\n items,\n columns,\n renderValue,\n getItemLabel,\n getItemHref,\n isCurrent,\n selectable,\n isSelected,\n onToggle,\n renderActions,\n sort,\n onSort,\n label,\n pageSelection,\n}: ListLayoutProps) {\n const intl = usePanneauIntl();\n const actions = items.map((item) => renderActions(item));\n const hasActions = actions.some((node) => node !== null);\n return (\n <div className={styles.scroller}>\n <table className={styles.table} aria-label={label}>\n <thead>\n <tr>\n {selectable ? <th className={styles.check}>{pageSelection}</th> : null}\n {columns.map((column) => {\n const direction = getSortDirection(sort, column);\n return (\n <th\n key={column.id}\n scope=\"col\"\n className={alignClass(column)}\n style={\n column.width !== undefined\n ? { width: column.width }\n : undefined\n }\n aria-sort={\n column.sortable === true ? (direction ?? 'none') : undefined\n }\n >\n {column.sortable === true ? (\n <button\n type=\"button\"\n className={cx(\n styles.sort,\n direction !== null && styles.sorted,\n )}\n onClick={() => onSort(column)}\n >\n {column.label ?? column.id}\n <span className={styles.sortIcon}>\n <Icon\n icon={\n direction === 'ascending'\n ? ArrowUp\n : direction === 'descending'\n ? ArrowDown\n : ArrowUpDown\n }\n size=\"sm\"\n />\n </span>\n </button>\n ) : (\n (column.label ?? column.id)\n )}\n </th>\n );\n })}\n {hasActions ? (\n <th className={styles.actionsCell}>\n <span className={styles.visuallyHidden}>\n {intl.formatMessage(messages.actions)}\n </span>\n </th>\n ) : null}\n </tr>\n </thead>\n <tbody>\n {items.map((item, row) => {\n const selected = selectable && isSelected(item);\n const href = getItemHref?.(item) ?? null;\n const current = isCurrent?.(item) ?? false;\n return (\n <tr\n key={item.id}\n data-selected={selected || undefined}\n data-current={current || undefined}\n >\n {selectable ? (\n <td className={styles.check}>\n <Checkbox\n aria-label={intl.formatMessage(messages.selectItem, {\n item: getItemLabel(item),\n })}\n isSelected={selected}\n onChange={() => onToggle(item)}\n />\n </td>\n ) : null}\n {columns.map((column, index) => (\n <td\n key={column.id}\n className={cx(\n alignClass(column),\n index === 0 && styles.title,\n )}\n >\n <span className={styles.cellLabel}>\n {column.label ?? column.id}\n </span>\n <span>\n {index === 0 ? (\n <ItemTitle href={href} current={current}>\n {renderValue(item, column)}\n </ItemTitle>\n ) : (\n renderValue(item, column)\n )}\n </span>\n </td>\n ))}\n {hasActions ? (\n <td className={styles.actionsCell}>{actions[row]}</td>\n ) : null}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"builtIn.js","names":[],"sources":["../../src/layouts/builtIn.ts"],"sourcesContent":["import type { ListLayoutEntry } from '../types';\nimport { CardsLayout } from './CardsLayout';\nimport { TableLayout } from './TableLayout';\n\n/** The built-in list layouts, by id. `gallery` and `calendar` come later. */\nexport const builtInLayouts: Readonly<Record<string, ListLayoutEntry>> & {\n table: ListLayoutEntry;\n} = {\n table: TableLayout,\n cards: CardsLayout,\n};\n"],"mappings":";;;;AAKA,IAAa,iBAET;CACA,OAAO;CACP,OAAO;AACX"}
1
+ {"version":3,"file":"builtIn.js","names":["ListLayoutEntry","CardsLayout","TableLayout","builtInLayouts","Readonly","Record","table","cards"],"sources":["../../src/layouts/builtIn.ts"],"sourcesContent":["import type { ListLayoutEntry } from '../types';\nimport { CardsLayout } from './CardsLayout';\nimport { TableLayout } from './TableLayout';\n\n/** The built-in list layouts, by id. `gallery` and `calendar` come later. */\nexport const builtInLayouts: Readonly<Record<string, ListLayoutEntry>> & {\n table: ListLayoutEntry;\n} = {\n table: TableLayout,\n cards: CardsLayout,\n};\n"],"mappings":";;;;AAKA,IAAaG,iBAET;CACAG,OAAOJ;CACPK,OAAON;AACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import { fr } from '@panneau/intl';\n\nimport { builtInDisplays } from './displays/displays';\nimport { builtInLayouts } from './layouts/builtIn';\nimport type { DisplayEntry, ListLayoutEntry } from './types';\n\n/**\n * The built-in displays and layouts as a `@panneau/core` plugin, with the French messages of every\n * Panneau package (from `@panneau/intl`). Lists use the built-in displays and layouts without it:\n * pass it for the messages, before the plugins that replace a display.\n */\nexport const listsPlugin: {\n id: string;\n displays: Readonly<Record<string, DisplayEntry>>;\n listLayouts: Readonly<Record<string, ListLayoutEntry>>;\n locales: Readonly<Record<string, Record<string, string>>>;\n} = {\n id: 'panneau-lists',\n displays: builtInDisplays,\n listLayouts: builtInLayouts,\n locales: { fr },\n};\n"],"mappings":";;;;;;;;;AAWA,IAAa,cAKT;CACA,IAAI;CACJ,UAAU;CACV,aAAa;CACb,SAAS,EAAE,GAAG;AAClB"}
1
+ {"version":3,"file":"plugin.js","names":["fr","builtInDisplays","builtInLayouts","DisplayEntry","ListLayoutEntry","listsPlugin","id","displays","Readonly","Record","listLayouts","locales"],"sources":["../src/plugin.ts"],"sourcesContent":["import { fr } from '@panneau/intl';\n\nimport { builtInDisplays } from './displays/displays';\nimport { builtInLayouts } from './layouts/builtIn';\nimport type { DisplayEntry, ListLayoutEntry } from './types';\n\n/**\n * The built-in displays and layouts as a `@panneau/core` plugin, with the French messages of every\n * Panneau package (from `@panneau/intl`). Lists use the built-in displays and layouts without it:\n * pass it for the messages, before the plugins that replace a display.\n */\nexport const listsPlugin: {\n id: string;\n displays: Readonly<Record<string, DisplayEntry>>;\n listLayouts: Readonly<Record<string, ListLayoutEntry>>;\n locales: Readonly<Record<string, Record<string, string>>>;\n} = {\n id: 'panneau-lists',\n displays: builtInDisplays,\n listLayouts: builtInLayouts,\n locales: { fr },\n};\n"],"mappings":";;;;;;;;;AAWA,IAAaK,cAKT;CACAC,IAAI;CACJC,UAAUN;CACVS,aAAaR;CACbS,SAAS,EAAEX,GAAG;AAClB"}
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","names":[],"sources":["../src/query.ts"],"sourcesContent":["import type { ListQuery } from '@panneau/protocol';\nimport { isFilterRange, matchesFilterRange } from '@panneau/protocol/runtime';\n\nimport type { ListColumn, ListItem } from './types';\nimport { getColumnValue, toText } from './values';\n\nexport interface LocalQueryOptions {\n /** The columns: values of localized fields are compared in `locale`. */\n columns?: readonly ListColumn[];\n /** Locale of localized values and of the text comparison. Defaults to `en`. */\n locale?: string;\n}\n\nexport interface LocalQueryResult<T extends ListItem> {\n /** The items of the page. */\n items: T[];\n /** How many items match the filters and the search, on every page. */\n total: number;\n}\n\nfunction valueOf(item: ListItem, key: string, options: LocalQueryOptions): unknown {\n const column = options.columns?.find((candidate) => candidate.id === key);\n return column !== undefined ? getColumnValue(item, column, options.locale ?? 'en') : item[key];\n}\n\n/**\n * Applies a list query to items in memory, as a backend would: filters (the value, or one of the\n * values, matches as a string; a range matches the values within its bounds), search in every text\n * value, sort, then the page. For a product that has every item at hand.\n */\nexport function applyListQuery<T extends ListItem>(\n items: readonly T[],\n query: ListQuery,\n options: LocalQueryOptions = {},\n): LocalQueryResult<T> {\n const locale = options.locale ?? 'en';\n let result = [...items];\n Object.entries(query.filter ?? {}).forEach(([key, expected]) => {\n if (isFilterRange(expected)) {\n result = result.filter((item) =>\n matchesFilterRange(valueOf(item, key, options), expected),\n );\n return;\n }\n const accepted = (Array.isArray(expected) ? expected : [expected]).map(String);\n result = result.filter((item) => {\n const value = valueOf(item, key, options);\n const values: unknown[] = Array.isArray(value) ? value : [value];\n return values.some((candidate) => {\n const id =\n candidate !== null && typeof candidate === 'object' && 'id' in candidate\n ? candidate.id\n : candidate;\n return accepted.includes(String(id));\n });\n });\n });\n const q = query.q?.trim().toLocaleLowerCase(locale) ?? '';\n if (q !== '') {\n result = result.filter((item) =>\n Object.entries(item)\n .filter(([key]) => key !== 'id' && key !== 'abilities' && key !== 'version')\n .some(([key]) =>\n toText(valueOf(item, key, options), locale)\n .toLocaleLowerCase(locale)\n .includes(q),\n ),\n );\n }\n const sort = query.sort ?? [];\n if (sort.length > 0) {\n const collator = new Intl.Collator(locale, { numeric: true, sensitivity: 'base' });\n result.sort((a, b) => {\n for (const part of sort) {\n const descending = part.startsWith('-');\n const key = descending ? part.slice(1) : part;\n const left = valueOf(a, key, options);\n const right = valueOf(b, key, options);\n const order =\n typeof left === 'number' && typeof right === 'number'\n ? left - right\n : compareText(toText(left, locale), toText(right, locale), collator);\n if (order !== 0) {\n return descending ? -order : order;\n }\n }\n return 0;\n });\n }\n const total = result.length;\n if (query.perPage !== undefined) {\n const page = query.page ?? 1;\n result = result.slice((page - 1) * query.perPage, page * query.perPage);\n }\n return { items: result, total };\n}\n\n/** Compares texts, empty ones last. */\nfunction compareText(left: string, right: string, collator: Intl.Collator): number {\n if (left === right) {\n return 0;\n }\n if (left === '') {\n return 1;\n }\n if (right === '') {\n return -1;\n }\n return collator.compare(left, right);\n}\n"],"mappings":";;;AAoBA,SAAS,QAAQ,MAAgB,KAAa,SAAqC;CAC/E,MAAM,SAAS,QAAQ,SAAS,MAAM,cAAc,UAAU,OAAO,GAAG;CACxE,OAAO,WAAW,KAAA,IAAY,eAAe,MAAM,QAAQ,QAAQ,UAAU,IAAI,IAAI,KAAK;AAC9F;;;;;;AAOA,SAAgB,eACZ,OACA,OACA,UAA6B,CAAC,GACX;CACnB,MAAM,SAAS,QAAQ,UAAU;CACjC,IAAI,SAAS,CAAC,GAAG,KAAK;CACtB,OAAO,QAAQ,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,cAAc;EAC5D,IAAI,cAAc,QAAQ,GAAG;GACzB,SAAS,OAAO,QAAQ,SACpB,mBAAmB,QAAQ,MAAM,KAAK,OAAO,GAAG,QAAQ,CAC5D;GACA;EACJ;EACA,MAAM,YAAY,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAA,CAAG,IAAI,MAAM;EAC7E,SAAS,OAAO,QAAQ,SAAS;GAC7B,MAAM,QAAQ,QAAQ,MAAM,KAAK,OAAO;GAExC,QAD0B,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK,EAAA,CACjD,MAAM,cAAc;IAC9B,MAAM,KACF,cAAc,QAAQ,OAAO,cAAc,YAAY,QAAQ,YACzD,UAAU,KACV;IACV,OAAO,SAAS,SAAS,OAAO,EAAE,CAAC;GACvC,CAAC;EACL,CAAC;CACL,CAAC;CACD,MAAM,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,kBAAkB,MAAM,KAAK;CACvD,IAAI,MAAM,IACN,SAAS,OAAO,QAAQ,SACpB,OAAO,QAAQ,IAAI,CAAC,CACf,QAAQ,CAAC,SAAS,QAAQ,QAAQ,QAAQ,eAAe,QAAQ,SAAS,CAAC,CAC3E,MAAM,CAAC,SACJ,OAAO,QAAQ,MAAM,KAAK,OAAO,GAAG,MAAM,CAAC,CACtC,kBAAkB,MAAM,CAAC,CACzB,SAAS,CAAC,CACnB,CACR;CAEJ,MAAM,OAAO,MAAM,QAAQ,CAAA;CAC3B,IAAI,KAAK,SAAS,GAAG;EACjB,MAAM,WAAW,IAAI,KAAK,SAAS,QAAQ;GAAE,SAAS;GAAM,aAAa;EAAO,CAAC;EACjF,OAAO,MAAM,GAAG,MAAM;GAClB,KAAK,MAAM,QAAQ,MAAM;IACrB,MAAM,aAAa,KAAK,WAAW,GAAG;IACtC,MAAM,MAAM,aAAa,KAAK,MAAM,CAAC,IAAI;IACzC,MAAM,OAAO,QAAQ,GAAG,KAAK,OAAO;IACpC,MAAM,QAAQ,QAAQ,GAAG,KAAK,OAAO;IACrC,MAAM,QACF,OAAO,SAAS,YAAY,OAAO,UAAU,WACvC,OAAO,QACP,YAAY,OAAO,MAAM,MAAM,GAAG,OAAO,OAAO,MAAM,GAAG,QAAQ;IAC3E,IAAI,UAAU,GACV,OAAO,aAAa,CAAC,QAAQ;GAErC;GACA,OAAO;EACX,CAAC;CACL;CACA,MAAM,QAAQ,OAAO;CACrB,IAAI,MAAM,YAAY,KAAA,GAAW;EAC7B,MAAM,OAAO,MAAM,QAAQ;EAC3B,SAAS,OAAO,OAAO,OAAO,KAAK,MAAM,SAAS,OAAO,MAAM,OAAO;CAC1E;CACA,OAAO;EAAE,OAAO;EAAQ;CAAM;AAClC;;AAGA,SAAS,YAAY,MAAc,OAAe,UAAiC;CAC/E,IAAI,SAAS,OACT,OAAO;CAEX,IAAI,SAAS,IACT,OAAO;CAEX,IAAI,UAAU,IACV,OAAO;CAEX,OAAO,SAAS,QAAQ,MAAM,KAAK;AACvC"}
1
+ {"version":3,"file":"query.js","names":["ListQuery","isFilterRange","matchesFilterRange","ListColumn","ListItem","getColumnValue","toText","LocalQueryOptions","columns","locale","LocalQueryResult","items","T","total","valueOf","item","key","options","column","find","candidate","id","undefined","applyListQuery","query","result","Object","entries","filter","forEach","expected","accepted","Array","isArray","map","String","value","values","some","includes","q","trim","toLocaleLowerCase","sort","length","collator","Intl","Collator","numeric","sensitivity","a","b","part","descending","startsWith","slice","left","right","order","compareText","perPage","page","compare"],"sources":["../src/query.ts"],"sourcesContent":["import type { ListQuery } from '@panneau/protocol';\nimport { isFilterRange, matchesFilterRange } from '@panneau/protocol/runtime';\n\nimport type { ListColumn, ListItem } from './types';\nimport { getColumnValue, toText } from './values';\n\nexport interface LocalQueryOptions {\n /** The columns: values of localized fields are compared in `locale`. */\n columns?: readonly ListColumn[];\n /** Locale of localized values and of the text comparison. Defaults to `en`. */\n locale?: string;\n}\n\nexport interface LocalQueryResult<T extends ListItem> {\n /** The items of the page. */\n items: T[];\n /** How many items match the filters and the search, on every page. */\n total: number;\n}\n\nfunction valueOf(item: ListItem, key: string, options: LocalQueryOptions): unknown {\n const column = options.columns?.find((candidate) => candidate.id === key);\n return column !== undefined ? getColumnValue(item, column, options.locale ?? 'en') : item[key];\n}\n\n/**\n * Applies a list query to items in memory, as a backend would: filters (the value, or one of the\n * values, matches as a string; a range matches the values within its bounds), search in every text\n * value, sort, then the page. For a product that has every item at hand.\n */\nexport function applyListQuery<T extends ListItem>(\n items: readonly T[],\n query: ListQuery,\n options: LocalQueryOptions = {},\n): LocalQueryResult<T> {\n const locale = options.locale ?? 'en';\n let result = [...items];\n Object.entries(query.filter ?? {}).forEach(([key, expected]) => {\n if (isFilterRange(expected)) {\n result = result.filter((item) =>\n matchesFilterRange(valueOf(item, key, options), expected),\n );\n return;\n }\n const accepted = (Array.isArray(expected) ? expected : [expected]).map(String);\n result = result.filter((item) => {\n const value = valueOf(item, key, options);\n const values: unknown[] = Array.isArray(value) ? value : [value];\n return values.some((candidate) => {\n const id =\n candidate !== null && typeof candidate === 'object' && 'id' in candidate\n ? candidate.id\n : candidate;\n return accepted.includes(String(id));\n });\n });\n });\n const q = query.q?.trim().toLocaleLowerCase(locale) ?? '';\n if (q !== '') {\n result = result.filter((item) =>\n Object.entries(item)\n .filter(([key]) => key !== 'id' && key !== 'abilities' && key !== 'version')\n .some(([key]) =>\n toText(valueOf(item, key, options), locale)\n .toLocaleLowerCase(locale)\n .includes(q),\n ),\n );\n }\n const sort = query.sort ?? [];\n if (sort.length > 0) {\n const collator = new Intl.Collator(locale, { numeric: true, sensitivity: 'base' });\n result.sort((a, b) => {\n for (const part of sort) {\n const descending = part.startsWith('-');\n const key = descending ? part.slice(1) : part;\n const left = valueOf(a, key, options);\n const right = valueOf(b, key, options);\n const order =\n typeof left === 'number' && typeof right === 'number'\n ? left - right\n : compareText(toText(left, locale), toText(right, locale), collator);\n if (order !== 0) {\n return descending ? -order : order;\n }\n }\n return 0;\n });\n }\n const total = result.length;\n if (query.perPage !== undefined) {\n const page = query.page ?? 1;\n result = result.slice((page - 1) * query.perPage, page * query.perPage);\n }\n return { items: result, total };\n}\n\n/** Compares texts, empty ones last. */\nfunction compareText(left: string, right: string, collator: Intl.Collator): number {\n if (left === right) {\n return 0;\n }\n if (left === '') {\n return 1;\n }\n if (right === '') {\n return -1;\n }\n return collator.compare(left, right);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"selection.js","names":[],"sources":["../src/selection.ts"],"sourcesContent":["import type { ListSelection } from '@panneau/core';\n\nimport type { ListItem } from './types';\n\n// The selection is read from the subscribed state, not through the methods of the list\n// (`list.isSelected()`): under the React Compiler, a component that calls a method of an object\n// that doesn't change would keep its first result.\n\n/** Whether an item is selected. */\nexport function isItemSelected(selection: ListSelection, id: string): boolean {\n return selection.mode === 'all' ? !selection.except.includes(id) : selection.ids.includes(id);\n}\n\n/** How many items are selected, given the total of the list (or the count of items without it). */\nexport function countSelected(selection: ListSelection, total: number): number {\n return selection.mode === 'all'\n ? Math.max(0, total - selection.except.length)\n : selection.ids.length;\n}\n\n/** Whether every, some or none of the items of a page are selected. */\nexport function getPageSelection(\n selection: ListSelection,\n items: readonly ListItem[],\n): 'all' | 'some' | 'none' {\n const selected = items.filter((item) => isItemSelected(selection, item.id)).length;\n if (selected === 0 || items.length === 0) {\n return 'none';\n }\n return selected === items.length ? 'all' : 'some';\n}\n"],"mappings":";;AASA,SAAgB,eAAe,WAA0B,IAAqB;CAC1E,OAAO,UAAU,SAAS,QAAQ,CAAC,UAAU,OAAO,SAAS,EAAE,IAAI,UAAU,IAAI,SAAS,EAAE;AAChG;;AAGA,SAAgB,cAAc,WAA0B,OAAuB;CAC3E,OAAO,UAAU,SAAS,QACpB,KAAK,IAAI,GAAG,QAAQ,UAAU,OAAO,MAAM,IAC3C,UAAU,IAAI;AACxB;;AAGA,SAAgB,iBACZ,WACA,OACuB;CACvB,MAAM,WAAW,MAAM,QAAQ,SAAS,eAAe,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC;CAC5E,IAAI,aAAa,KAAK,MAAM,WAAW,GACnC,OAAO;CAEX,OAAO,aAAa,MAAM,SAAS,QAAQ;AAC/C"}
1
+ {"version":3,"file":"selection.js","names":["ListSelection","ListItem","isItemSelected","selection","id","mode","except","includes","ids","countSelected","total","Math","max","length","getPageSelection","items","selected","filter","item"],"sources":["../src/selection.ts"],"sourcesContent":["import type { ListSelection } from '@panneau/core';\n\nimport type { ListItem } from './types';\n\n// The selection is read from the subscribed state, not through the methods of the list\n// (`list.isSelected()`): under the React Compiler, a component that calls a method of an object\n// that doesn't change would keep its first result.\n\n/** Whether an item is selected. */\nexport function isItemSelected(selection: ListSelection, id: string): boolean {\n return selection.mode === 'all' ? !selection.except.includes(id) : selection.ids.includes(id);\n}\n\n/** How many items are selected, given the total of the list (or the count of items without it). */\nexport function countSelected(selection: ListSelection, total: number): number {\n return selection.mode === 'all'\n ? Math.max(0, total - selection.except.length)\n : selection.ids.length;\n}\n\n/** Whether every, some or none of the items of a page are selected. */\nexport function getPageSelection(\n selection: ListSelection,\n items: readonly ListItem[],\n): 'all' | 'some' | 'none' {\n const selected = items.filter((item) => isItemSelected(selection, item.id)).length;\n if (selected === 0 || items.length === 0) {\n return 'none';\n }\n return selected === items.length ? 'all' : 'some';\n}\n"],"mappings":";;AASA,SAAgBE,eAAeC,WAA0BC,IAAqB;CAC1E,OAAOD,UAAUE,SAAS,QAAQ,CAACF,UAAUG,OAAOC,SAASH,EAAE,IAAID,UAAUK,IAAID,SAASH,EAAE;AAChG;;AAGA,SAAgBK,cAAcN,WAA0BO,OAAuB;CAC3E,OAAOP,UAAUE,SAAS,QACpBM,KAAKC,IAAI,GAAGF,QAAQP,UAAUG,OAAOO,MAAM,IAC3CV,UAAUK,IAAIK;AACxB;;AAGA,SAAgBC,iBACZX,WACAY,OACuB;CACvB,MAAMC,WAAWD,MAAME,QAAQC,SAAShB,eAAeC,WAAWe,KAAKd,EAAE,CAAC,CAAC,CAACS;CAC5E,IAAIG,aAAa,KAAKD,MAAMF,WAAW,GACnC,OAAO;CAEX,OAAOG,aAAaD,MAAMF,SAAS,QAAQ;AAC/C"}
@@ -1,9 +1,9 @@
1
1
  import { messages } from "../messages.js";
2
2
  import Toolbar_module_default from "./Toolbar.module.js";
3
+ import { c } from "react/compiler-runtime";
3
4
  import { Icon, Tooltip, usePanneauIntl } from "@panneau/ui";
4
5
  import { jsx } from "react/jsx-runtime";
5
6
  import { LayoutGrid, Rows3, Square } from "lucide-react";
6
- import { c } from "react/compiler-runtime";
7
7
  import { ToggleButton, ToggleButtonGroup } from "react-aria-components";
8
8
  //#region src/toolbar/LayoutSwitch.tsx
9
9
  var ICONS = {
@@ -1 +1 @@
1
- {"version":3,"file":"LayoutSwitch.js","names":["layout","label","_c","styles"],"sources":["../../src/toolbar/LayoutSwitch.tsx"],"sourcesContent":["import { LayoutGrid, type LucideIcon, Rows3, Square } from 'lucide-react';\nimport { ToggleButton, ToggleButtonGroup } from 'react-aria-components';\n\nimport { Icon, Tooltip, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport styles from './Toolbar.module.css';\n\nconst ICONS: Record<string, LucideIcon> = { table: Rows3, cards: LayoutGrid };\n\nexport interface LayoutSwitchProps {\n layouts: readonly string[];\n value: string;\n onChange: (layout: string) => void;\n}\n\n/** Buttons to show the items as a table, as cards, or in a plugin's layout. */\nexport function LayoutSwitch({ layouts, value, onChange }: LayoutSwitchProps) {\n const intl = usePanneauIntl();\n const labels: Record<string, string> = {\n table: intl.formatMessage(messages.layoutTable),\n cards: intl.formatMessage(messages.layoutCards),\n };\n return (\n <ToggleButtonGroup\n aria-label={intl.formatMessage(messages.layout)}\n selectionMode=\"single\"\n disallowEmptySelection\n selectedKeys={[value]}\n onSelectionChange={(keys) => {\n const [next] = [...keys];\n if (next !== undefined) {\n onChange(String(next));\n }\n }}\n className={styles.layouts}\n >\n {layouts.map((layout) => {\n const label = labels[layout] ?? layout;\n return (\n <Tooltip key={layout} content={label}>\n <ToggleButton\n id={layout}\n aria-label={label}\n className={styles.layoutButton}\n >\n <Icon icon={ICONS[layout] ?? Square} />\n </ToggleButton>\n </Tooltip>\n );\n })}\n </ToggleButtonGroup>\n );\n}\n"],"mappings":";;;;;;;;AAQA,IAAM,QAAoC;CAAE,OAAO;CAAO,OAAO;AAAW;;AAS5E,SAAO,aAAA,IAAA;CAAA,MAAA,IAAAE,EAAA,EAAA;CAAsB,MAAA,EAAA,SAAA,OAAA,aAAA;CACzB,MAAA,OAAa,eAAe;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EAEnB,KAAA,KAAI,cAAe,SAAQ,WAAY;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EACxC,KAAA,KAAI,cAAe,SAAQ,WAAY;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA,EAAA,OAAA,IAAA;EAFZ,KAAA;GAAA,OAC5B;GAAwC,OACxC;EACX;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAHD,MAAA,SAAuC;CAGrC,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EAGkB,KAAA,KAAI,cAAe,SAAQ,MAAO;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EAGjC,KAAA,CAAC,KAAK;EAAC,EAAA,KAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,UAAA;EACF,MAAA,SAAA;GACf,MAAA,CAAA,QAAe,CAAA,GAAI,IAAI;GACvB,IAAI,SAAS,KAAA,GACT,SAAS,OAAO,IAAI,CAAC;EACxB;EACJ,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,UAAA,EAAA,QAAA,SAAA;EAAA,IAAA;EAAA,IAAA,EAAA,QAAA,QAAA;GAGY,MAAA,WAAA;IACT,MAAA,QAAc,OAAO,WAAP;IAAyB,OAEnC,oBAAC,SAAD;KAA+BD,SAAA;KAC3B,UAAA,oBAAC,cAAD;MACQD,IAAA;MACQC,cAAA;MACD,WAAAE,uBAAM;MAEjB,UAAA,oBAAC,MAAD,EAAY,MAAA,MAAM,WAAN,OAAuB,CAAA;KAL1B,CAAA;IADT,GAAM,MAAN;GAQE;GAEjB,EAAA,MAAA;GAAA,EAAA,MAAA;EAAA,OAAA,KAAA,EAAA;EAbA,KAAA,QAAO,IAAK,EAaZ;EAAC,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,IAAA;EA1BN,KAAA,oBAAC,mBAAD;GACgB,cAAA;GACE,eAAA;GACd,wBAAA;GACc,cAAA;GACK,mBAAA;GAMR,WAAAA,uBAAM;GAEhB,UAAA;EAba,CAAA;EA2BE,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OA3BpB;AA2BoB"}
1
+ {"version":3,"file":"LayoutSwitch.js","names":["LayoutGrid","LucideIcon","Rows3","Square","ToggleButton","ToggleButtonGroup","Icon","Tooltip","usePanneauIntl","messages","styles","ICONS","Record","table","cards","LayoutSwitchProps","layouts","value","onChange","layout","LayoutSwitch","t0","$","_c","intl","t1","formatMessage","layoutTable","t2","layoutCards","t3","labels","t4","t5","t6","keys","next","undefined","String","t7","t8","label","layoutButton","map","_c","styles"],"sources":["../../src/toolbar/LayoutSwitch.tsx"],"sourcesContent":["import { LayoutGrid, type LucideIcon, Rows3, Square } from 'lucide-react';\nimport { ToggleButton, ToggleButtonGroup } from 'react-aria-components';\n\nimport { Icon, Tooltip, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport styles from './Toolbar.module.css';\n\nconst ICONS: Record<string, LucideIcon> = { table: Rows3, cards: LayoutGrid };\n\nexport interface LayoutSwitchProps {\n layouts: readonly string[];\n value: string;\n onChange: (layout: string) => void;\n}\n\n/** Buttons to show the items as a table, as cards, or in a plugin's layout. */\nexport function LayoutSwitch({ layouts, value, onChange }: LayoutSwitchProps) {\n const intl = usePanneauIntl();\n const labels: Record<string, string> = {\n table: intl.formatMessage(messages.layoutTable),\n cards: intl.formatMessage(messages.layoutCards),\n };\n return (\n <ToggleButtonGroup\n aria-label={intl.formatMessage(messages.layout)}\n selectionMode=\"single\"\n disallowEmptySelection\n selectedKeys={[value]}\n onSelectionChange={(keys) => {\n const [next] = [...keys];\n if (next !== undefined) {\n onChange(String(next));\n }\n }}\n className={styles.layouts}\n >\n {layouts.map((layout) => {\n const label = labels[layout] ?? layout;\n return (\n <Tooltip key={layout} content={label}>\n <ToggleButton\n id={layout}\n aria-label={label}\n className={styles.layoutButton}\n >\n <Icon icon={ICONS[layout] ?? Square} />\n </ToggleButton>\n </Tooltip>\n );\n })}\n </ToggleButtonGroup>\n );\n}\n"],"mappings":";;;;;;;;AAQA,IAAMW,QAAoC;CAAEE,OAAOX;CAAOY,OAAOd;AAAW;;AAS5E,SAAOoB,aAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAsB,MAAA,EAAAP,SAAAC,OAAAC,aAAAG;CACzB,MAAAG,OAAahB,eAAe;CAAE,IAAAiB;CAAA,IAAAH,EAAA,OAAAE,MAAA;EAEnBC,KAAAD,KAAIE,cAAejB,SAAQkB,WAAY;EAACL,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAAA,IAAAM;CAAA,IAAAN,EAAA,OAAAE,MAAA;EACxCI,KAAAJ,KAAIE,cAAejB,SAAQoB,WAAY;EAACP,EAAA,KAAAE;EAAAF,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAA,IAAAQ;CAAA,IAAAR,EAAA,OAAAG,MAAAH,EAAA,OAAAM,IAAA;EAFZE,KAAA;GAAAjB,OAC5BY;GAAwCX,OACxCc;EACX;EAACN,EAAA,KAAAG;EAAAH,EAAA,KAAAM;EAAAN,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAHD,MAAAS,SAAuCD;CAGrC,IAAAE;CAAA,IAAAV,EAAA,OAAAE,MAAA;EAGkBQ,KAAAR,KAAIE,cAAejB,SAAQU,MAAO;EAACG,EAAA,KAAAE;EAAAF,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,IAAAW;CAAA,IAAAX,EAAA,OAAAL,OAAA;EAGjCgB,KAAA,CAAChB,KAAK;EAACK,EAAA,KAAAL;EAAAK,EAAA,MAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,IAAAY;CAAA,IAAAZ,EAAA,QAAAJ,UAAA;EACFgB,MAAAC,SAAA;GACf,MAAA,CAAAC,QAAe,CAAA,GAAID,IAAI;GACvB,IAAIC,SAASC,KAAAA,GACTnB,SAASoB,OAAOF,IAAI,CAAC;EACxB;EACJd,EAAA,MAAAJ;EAAAI,EAAA,MAAAY;CAAA,OAAAA,KAAAZ,EAAA;CAAA,IAAAiB;CAAA,IAAAjB,EAAA,QAAAS,UAAAT,EAAA,QAAAN,SAAA;EAAA,IAAAwB;EAAA,IAAAlB,EAAA,QAAAS,QAAA;GAGYS,MAAArB,WAAA;IACT,MAAAsB,QAAcV,OAAOZ,WAAPA;IAAyB,OAEnC,oBAAC,SAAD;KAA+BsB,SAAAA;KAC3B,UAAA,oBAAC,cAAD;MACQtB,IAAAA;MACQsB,cAAAA;MACD,WAAA/B,uBAAMgC;MAEjB,UAAA,oBAAC,MAAD,EAAY,MAAA/B,MAAMQ,WAANhB,OAAuB,CAAA;KAL1B,CAAA;IADT,GAAMgB,MAAN;GAQE;GAEjBG,EAAA,MAAAS;GAAAT,EAAA,MAAAkB;EAAA,OAAAA,KAAAlB,EAAA;EAbAiB,KAAAvB,QAAO2B,IAAKH,EAaZ;EAAClB,EAAA,MAAAS;EAAAT,EAAA,MAAAN;EAAAM,EAAA,MAAAiB;CAAA,OAAAA,KAAAjB,EAAA;CAAA,IAAAkB;CAAA,IAAAlB,EAAA,QAAAU,MAAAV,EAAA,QAAAW,MAAAX,EAAA,QAAAY,MAAAZ,EAAA,QAAAiB,IAAA;EA1BNC,KAAA,oBAAC,mBAAD;GACgB,cAAAR;GACE,eAAA;GACd,wBAAA;GACc,cAAAC;GACK,mBAAAC;GAMR,WAAAxB,uBAAMM;GAEhBuB,UAAAA;EAba,CAAA;EA2BEjB,EAAA,MAAAU;EAAAV,EAAA,MAAAW;EAAAX,EAAA,MAAAY;EAAAZ,EAAA,MAAAiB;EAAAjB,EAAA,MAAAkB;CAAA,OAAAA,KAAAlB,EAAA;CAAA,OA3BpBkB;AA2BoB"}