@planningcenter/tapestry 4.10.0-rc.10 → 4.10.0-rc.12

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.
@@ -64,8 +64,10 @@ export type FilterNode = FilterNodeItem | FilterNodeGroup;
64
64
  /** Narrow a factory's operator set by name. `includes` keeps only the named operators, in the order given; `excludes` drops them. */
65
65
  export type OperatorSelection<Name extends string = string> = {
66
66
  excludes?: never;
67
+ /** Keeps only these operators, in this order. Can't be combined with `excludes`. */
67
68
  includes?: Name[];
68
69
  } | {
70
+ /** Drops these operators from the defaults. Can't be combined with `includes`. */
69
71
  excludes?: Name[];
70
72
  includes?: never;
71
73
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FilterTypes.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/FilterTypes.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FilterTypes.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/FilterTypes.tsx"],"names":[],"mappings":"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"}
@@ -34,9 +34,12 @@ declare const ALL_COLLECTION_OPERATORS: ({
34
34
  })[];
35
35
  export type CollectionOperatorName = (typeof ALL_COLLECTION_OPERATORS)[number]["name"];
36
36
  export type CollectionFilterConfig = FilterItemConfig<CollectionOperatorName> & {
37
+ /** The choices, or a function that loads them. A function receives the combobox's search query and, inside a `scopedFilter`, the chosen scope. */
37
38
  options: CollectionOptions;
38
39
  } & ({
40
+ /** How the editor presents the options. `checkboxes` renders radios when `multiple` is false. Defaults to `select`. */
39
41
  display?: CollectionDisplay;
42
+ /** Allows picking more than one option. Not supported with the `select` display. */
40
43
  multiple?: false;
41
44
  } | {
42
45
  display?: Exclude<CollectionDisplay, "select">;
@@ -1 +1 @@
1
- {"version":3,"file":"collectionFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/collectionFilter.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,2BAA2B,CAAA;AAElC,OAAO,KAAK,EAGV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAItB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAA;AAEpE,eAAO,MAAM,aAAa;;;;;;CAIG,CAAA;AAC7B,eAAO,MAAM,cAAc;;;;;;CAIE,CAAA;AAE7B,QAAA,MAAM,wBAAwB;;;;;;;;;;;;IAAkC,CAAA;AAGhE,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnD,MAAM,MAAM,sBAAsB,GAChC,gBAAgB,CAAC,sBAAsB,CAAC,GAAG;IACzC,OAAO,EAAE,iBAAiB,CAAA;CAC3B,GAAG,CACE;IAAE,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GACjD;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CACrE,CAAA;AAEL,wBAAgB,gBAAgB,CAAC,EAC/B,OAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,QAAgB,EAChB,OAAO,EACP,GAAG,MAAM,EACV,EAAE,sBAAsB,GAAG,cAAc,CAmBzC"}
1
+ {"version":3,"file":"collectionFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/collectionFilter.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,2BAA2B,CAAA;AAElC,OAAO,KAAK,EAGV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAItB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAA;AAEpE,eAAO,MAAM,aAAa;;;;;;CAIG,CAAA;AAC7B,eAAO,MAAM,cAAc;;;;;;CAIE,CAAA;AAE7B,QAAA,MAAM,wBAAwB;;;;;;;;;;;;IAAkC,CAAA;AAGhE,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnD,MAAM,MAAM,sBAAsB,GAChC,gBAAgB,CAAC,sBAAsB,CAAC,GAAG;IACzC,kJAAkJ;IAClJ,OAAO,EAAE,iBAAiB,CAAA;CAC3B,GAAG,CACE;IACE,uHAAuH;IACvH,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB,GACD;IACE,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAA;IAC9C,QAAQ,EAAE,IAAI,CAAA;CACf,CACJ,CAAA;AAEL,wBAAgB,gBAAgB,CAAC,EAC/B,OAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,QAAgB,EAChB,OAAO,EACP,GAAG,MAAM,EACV,EAAE,sBAAsB,GAAG,cAAc,CAmBzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"collectionFilter.js","sources":["../../../src/components/DataTable/collectionFilter.tsx"],"sourcesContent":["import React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport { CollectionFilterEditorLazy } from \"./CollectionEditorsLazy\"\nimport type {\n CollectionFilterValue,\n CollectionOptions,\n} from \"./CollectionEditorsShared\"\nimport { CollectionFilterEditorStatic } from \"./CollectionEditorsStatic\"\nimport type {\n ActiveFilterLabel,\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\n// A type alias (not an interface) so it satisfies `Select`'s `data-*` index signature.\nexport type CollectionOption = {\n label: string\n value: string\n}\n\nexport type CollectionDisplay = \"checkboxes\" | \"combobox\" | \"select\"\n\nexport const COLLECTION_IS = {\n inputType: { type: \"collection\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const COLLECTION_NOT = {\n inputType: { type: \"collection\" },\n label: \"is not\",\n name: \"not\",\n} as const satisfies Operator\n\nconst ALL_COLLECTION_OPERATORS = [COLLECTION_IS, COLLECTION_NOT]\nconst DEFAULT_COLLECTION_OPERATORS = [COLLECTION_IS]\n\nexport type CollectionOperatorName =\n (typeof ALL_COLLECTION_OPERATORS)[number][\"name\"]\n\nexport type CollectionFilterConfig =\n FilterItemConfig<CollectionOperatorName> & {\n options: CollectionOptions\n } & (\n | { display?: CollectionDisplay; multiple?: false }\n | { display?: Exclude<CollectionDisplay, \"select\">; multiple: true }\n )\n\nexport function collectionFilter({\n display = \"select\",\n excludes,\n includes,\n multiple = false,\n options,\n ...config\n}: CollectionFilterConfig): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new CollectionActiveFilter(\n filter,\n operator,\n activeFilter.value as CollectionFilterValue,\n activeFilter.label,\n activeFilter.scope,\n { display, multiple, options }\n ),\n operators: resolveOperators(ALL_COLLECTION_OPERATORS, {\n default: DEFAULT_COLLECTION_OPERATORS,\n excludes,\n includes,\n }),\n }\n return filter\n}\n\nclass CollectionActiveFilter extends ActiveFilterInstance<CollectionFilterValue> {\n constructor(\n filter: FilterNodeItem,\n operator: FilterNodeItem[\"operators\"][number],\n value: CollectionFilterValue,\n private readonly label: ActiveFilterLabel,\n private readonly scope: string | undefined,\n private readonly config: {\n display: CollectionDisplay\n multiple: boolean\n options: CollectionOptions\n }\n ) {\n super(filter, operator, value)\n this.label = label\n }\n\n formatValue() {\n if (this.label) return Array.isArray(this.label) ? this.label : [this.label]\n const values = Array.isArray(this.value) ? this.value : [this.value]\n if (typeof this.config.options === \"function\") return [\"\"]\n return values\n .map(\n (value) =>\n (this.config.options as CollectionOption[]).find(\n (option) => option.value === value\n )?.label ?? value\n )\n .join(\", \")\n }\n\n renderEditor(onChange: FilterChange) {\n const hasLazyOptions = typeof this.config.options === \"function\"\n const Editor = hasLazyOptions\n ? CollectionFilterEditorLazy\n : CollectionFilterEditorStatic\n\n return (\n <Editor\n config={this.config}\n onChange={onChange}\n operator={this.operator}\n value={this.value}\n label={this.label}\n filter={this.filter}\n scope={this.scope}\n />\n )\n }\n}\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"collectionFilter.js","sources":["../../../src/components/DataTable/collectionFilter.tsx"],"sourcesContent":["import React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport { CollectionFilterEditorLazy } from \"./CollectionEditorsLazy\"\nimport type {\n CollectionFilterValue,\n CollectionOptions,\n} from \"./CollectionEditorsShared\"\nimport { CollectionFilterEditorStatic } from \"./CollectionEditorsStatic\"\nimport type {\n ActiveFilterLabel,\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\n// A type alias (not an interface) so it satisfies `Select`'s `data-*` index signature.\nexport type CollectionOption = {\n label: string\n value: string\n}\n\nexport type CollectionDisplay = \"checkboxes\" | \"combobox\" | \"select\"\n\nexport const COLLECTION_IS = {\n inputType: { type: \"collection\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const COLLECTION_NOT = {\n inputType: { type: \"collection\" },\n label: \"is not\",\n name: \"not\",\n} as const satisfies Operator\n\nconst ALL_COLLECTION_OPERATORS = [COLLECTION_IS, COLLECTION_NOT]\nconst DEFAULT_COLLECTION_OPERATORS = [COLLECTION_IS]\n\nexport type CollectionOperatorName =\n (typeof ALL_COLLECTION_OPERATORS)[number][\"name\"]\n\nexport type CollectionFilterConfig =\n FilterItemConfig<CollectionOperatorName> & {\n /** The choices, or a function that loads them. A function receives the combobox's search query and, inside a `scopedFilter`, the chosen scope. */\n options: CollectionOptions\n } & (\n | {\n /** How the editor presents the options. `checkboxes` renders radios when `multiple` is false. Defaults to `select`. */\n display?: CollectionDisplay\n /** Allows picking more than one option. Not supported with the `select` display. */\n multiple?: false\n }\n | {\n display?: Exclude<CollectionDisplay, \"select\">\n multiple: true\n }\n )\n\nexport function collectionFilter({\n display = \"select\",\n excludes,\n includes,\n multiple = false,\n options,\n ...config\n}: CollectionFilterConfig): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new CollectionActiveFilter(\n filter,\n operator,\n activeFilter.value as CollectionFilterValue,\n activeFilter.label,\n activeFilter.scope,\n { display, multiple, options }\n ),\n operators: resolveOperators(ALL_COLLECTION_OPERATORS, {\n default: DEFAULT_COLLECTION_OPERATORS,\n excludes,\n includes,\n }),\n }\n return filter\n}\n\nclass CollectionActiveFilter extends ActiveFilterInstance<CollectionFilterValue> {\n constructor(\n filter: FilterNodeItem,\n operator: FilterNodeItem[\"operators\"][number],\n value: CollectionFilterValue,\n private readonly label: ActiveFilterLabel,\n private readonly scope: string | undefined,\n private readonly config: {\n display: CollectionDisplay\n multiple: boolean\n options: CollectionOptions\n }\n ) {\n super(filter, operator, value)\n this.label = label\n }\n\n formatValue() {\n if (this.label) return Array.isArray(this.label) ? this.label : [this.label]\n const values = Array.isArray(this.value) ? this.value : [this.value]\n if (typeof this.config.options === \"function\") return [\"\"]\n return values\n .map(\n (value) =>\n (this.config.options as CollectionOption[]).find(\n (option) => option.value === value\n )?.label ?? value\n )\n .join(\", \")\n }\n\n renderEditor(onChange: FilterChange) {\n const hasLazyOptions = typeof this.config.options === \"function\"\n const Editor = hasLazyOptions\n ? CollectionFilterEditorLazy\n : CollectionFilterEditorStatic\n\n return (\n <Editor\n config={this.config}\n onChange={onChange}\n operator={this.operator}\n value={this.value}\n label={this.label}\n filter={this.filter}\n scope={this.scope}\n />\n )\n }\n}\n"],"names":["React"],"mappings":"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"}
@@ -84,7 +84,9 @@ declare const ALL_DATE_OPERATORS: ({
84
84
  export type DateOperatorName = (typeof ALL_DATE_OPERATORS)[number]["name"];
85
85
  /** Inclusive bounds on the dates the filter's pickers allow. */
86
86
  export interface DateLimits {
87
+ /** Latest selectable date, as a `DateValue` or ISO date string. */
87
88
  max?: DatePickerDateValue;
89
+ /** Earliest selectable date, as a `DateValue` or ISO date string. */
88
90
  min?: DatePickerDateValue;
89
91
  }
90
92
  export declare function dateFilter({ excludes, includes, max, min, ...config }: FilterItemConfig<DateOperatorName> & DateLimits): FilterNodeItem;
@@ -1 +1 @@
1
- {"version":3,"file":"dateFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/dateFilter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAW9E,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAGtB,sDAAsD;AACtD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAIvD,eAAO,MAAM,OAAO;;;;;;CAIS,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,UAAU;;;;;;CAIM,CAAA;AAE7B,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAA0C,CAAA;AAGlE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAuB1E,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,mBAAmB,CAAA;IACzB,GAAG,CAAC,EAAE,mBAAmB,CAAA;CAC1B;AAcD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,GAAG,EACH,GAAG,MAAM,EACV,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,UAAU,GAAG,cAAc,CAiBlE"}
1
+ {"version":3,"file":"dateFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/dateFilter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAW9E,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAGtB,sDAAsD;AACtD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAIvD,eAAO,MAAM,OAAO;;;;;;CAIS,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,UAAU;;;;;;CAIM,CAAA;AAE7B,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAA0C,CAAA;AAGlE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAuB1E,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,GAAG,CAAC,EAAE,mBAAmB,CAAA;IACzB,qEAAqE;IACrE,GAAG,CAAC,EAAE,mBAAmB,CAAA;CAC1B;AAcD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,GAAG,EACH,GAAG,MAAM,EACV,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,UAAU,GAAG,cAAc,CAiBlE"}
@@ -1 +1 @@
1
- {"version":3,"file":"dateFilter.js","sources":["../../../src/components/DataTable/dateFilter.tsx"],"sourcesContent":["import { DatePicker, type DatePickerDateValue } from \"@components/date-picker\"\nimport { Flex } from \"@components/flex\"\nimport {\n DateFormatter,\n type DateValue,\n getLocalTimeZone,\n parseDate,\n} from \"@internationalized/date\"\nimport React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\n/** ISO `YYYY-MM-DD` strings; a pair for `between`. */\nexport type DateFilterValue = string | [string, string]\n\ntype DateRange = [string | undefined, string | undefined]\n\nexport const DATE_IS = {\n inputType: { type: \"date\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const LT = {\n inputType: { type: \"date\" },\n label: \"is before\",\n name: \"lt\",\n} as const satisfies Operator\nexport const GT = {\n inputType: { type: \"date\" },\n label: \"is after\",\n name: \"gt\",\n} as const satisfies Operator\nexport const LTE = {\n inputType: { type: \"date\" },\n label: \"is on or before\",\n name: \"lte\",\n} as const satisfies Operator\nexport const GTE = {\n inputType: { type: \"date\" },\n label: \"is on or after\",\n name: \"gte\",\n} as const satisfies Operator\nexport const DATE_RANGE = {\n inputType: { type: \"date-range\" },\n label: \"is between\",\n name: \"between\",\n} as const satisfies Operator\n\nconst ALL_DATE_OPERATORS = [DATE_IS, LT, GT, LTE, GTE, DATE_RANGE]\nconst DEFAULT_DATE_OPERATORS = [DATE_IS, LT, GT, DATE_RANGE]\n\nexport type DateOperatorName = (typeof ALL_DATE_OPERATORS)[number][\"name\"]\n\nconst formatter = new DateFormatter(\n new Intl.DateTimeFormat().resolvedOptions().locale,\n { dateStyle: \"medium\" }\n)\n\nconst formatDate = (iso: string) =>\n formatter.format(parseDate(iso).toDate(getLocalTimeZone()))\n\nconst toDateValue = (date: DatePickerDateValue) =>\n typeof date === \"string\" ? parseDate(date) : date\n\nfunction earlier(a?: DatePickerDateValue, b?: DatePickerDateValue) {\n if (a === undefined || b === undefined) return a ?? b\n return toDateValue(a).compare(toDateValue(b)) <= 0 ? a : b\n}\n\nfunction later(a?: DatePickerDateValue, b?: DatePickerDateValue) {\n if (a === undefined || b === undefined) return a ?? b\n return toDateValue(a).compare(toDateValue(b)) >= 0 ? a : b\n}\n\n/** Inclusive bounds on the dates the filter's pickers allow. */\nexport interface DateLimits {\n max?: DatePickerDateValue\n min?: DatePickerDateValue\n}\n\n/**\n * The pickers only flag typed dates outside the limits as invalid, so the\n * editors clear the value rather than commit them.\n */\nfunction toValidDate(date: DateValue | null, { max, min }: DateLimits) {\n if (!date) return undefined\n const isWithinLimits =\n (min === undefined || date.compare(toDateValue(min)) >= 0) &&\n (max === undefined || date.compare(toDateValue(max)) <= 0)\n return isWithinLimits ? date.toString() : undefined\n}\n\nexport function dateFilter({\n excludes,\n includes,\n max,\n min,\n ...config\n}: FilterItemConfig<DateOperatorName> & DateLimits): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new DateActiveFilter(\n filter,\n operator,\n activeFilter.value as DateFilterValue,\n { max, min }\n ),\n operators: resolveOperators(ALL_DATE_OPERATORS, {\n default: DEFAULT_DATE_OPERATORS,\n excludes,\n includes,\n }),\n }\n return filter\n}\n\nclass DateActiveFilter extends ActiveFilterInstance<DateFilterValue> {\n constructor(\n filter: FilterNodeItem,\n operator: Operator,\n value: DateFilterValue,\n readonly limits: DateLimits\n ) {\n super(filter, operator, value)\n }\n\n formatValue() {\n if (Array.isArray(this.value)) {\n const [start, end] = this.value\n if (start === undefined || end === undefined) {\n return [start, end].filter((date) => date !== undefined).map(formatDate)\n }\n return [formatDate(start), \"and\", formatDate(end)]\n }\n return this.value === undefined ? \"\" : formatDate(this.value)\n }\n\n renderEditor(onChange: FilterChange) {\n const { label } = this.operator\n\n if (this.operator.inputType.type === \"date-range\") {\n const range: DateRange = Array.isArray(this.value)\n ? this.value\n : [this.value, this.value]\n return (\n <DateRangeEditor\n label={label}\n max={this.limits.max}\n min={this.limits.min}\n value={range}\n onCommit={(value) => {\n const complete =\n value.length === 2 && value.every((v) => v !== undefined)\n onChange({ value }, { complete })\n }}\n />\n )\n }\n const single = Array.isArray(this.value) ? this.value[0] : this.value\n return (\n <DatePicker\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus\n hideLabel\n // Uncontrolled so a typed date outside the limits stays visible\n // (and flagged invalid) after the value is cleared.\n defaultValue={single}\n label={label}\n max={this.limits.max}\n min={this.limits.min}\n onChange={(date) => {\n const value = toValidDate(date, this.limits)\n onChange({ value }, { complete: value !== undefined })\n }}\n />\n )\n }\n}\n\nfunction DateRangeEditor({\n label,\n max,\n min,\n onCommit,\n value: [start, end],\n}: DateLimits & {\n label: string\n onCommit: (value: DateRange) => void\n value: DateRange\n}) {\n const startLimits = { max: earlier(max, end), min }\n const endLimits = { max, min: later(min, start) }\n\n return (\n <Flex align=\"center\" gap={1}>\n <DatePicker\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus\n hideLabel\n defaultValue={start}\n label={`${label} from`}\n max={startLimits.max}\n min={startLimits.min}\n onChange={(date) => onCommit([toValidDate(date, startLimits), end])}\n />\n <div>and</div>\n <DatePicker\n hideLabel\n defaultValue={end}\n label={`${label} to`}\n max={endLimits.max}\n min={endLimits.min}\n onChange={(date) => onCommit([start, toValidDate(date, endLimits)])}\n />\n </Flex>\n )\n}\n"],"names":["DateFormatter","parseDate","getLocalTimeZone","React"],"mappings":"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"}
1
+ {"version":3,"file":"dateFilter.js","sources":["../../../src/components/DataTable/dateFilter.tsx"],"sourcesContent":["import { DatePicker, type DatePickerDateValue } from \"@components/date-picker\"\nimport { Flex } from \"@components/flex\"\nimport {\n DateFormatter,\n type DateValue,\n getLocalTimeZone,\n parseDate,\n} from \"@internationalized/date\"\nimport React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\n/** ISO `YYYY-MM-DD` strings; a pair for `between`. */\nexport type DateFilterValue = string | [string, string]\n\ntype DateRange = [string | undefined, string | undefined]\n\nexport const DATE_IS = {\n inputType: { type: \"date\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const LT = {\n inputType: { type: \"date\" },\n label: \"is before\",\n name: \"lt\",\n} as const satisfies Operator\nexport const GT = {\n inputType: { type: \"date\" },\n label: \"is after\",\n name: \"gt\",\n} as const satisfies Operator\nexport const LTE = {\n inputType: { type: \"date\" },\n label: \"is on or before\",\n name: \"lte\",\n} as const satisfies Operator\nexport const GTE = {\n inputType: { type: \"date\" },\n label: \"is on or after\",\n name: \"gte\",\n} as const satisfies Operator\nexport const DATE_RANGE = {\n inputType: { type: \"date-range\" },\n label: \"is between\",\n name: \"between\",\n} as const satisfies Operator\n\nconst ALL_DATE_OPERATORS = [DATE_IS, LT, GT, LTE, GTE, DATE_RANGE]\nconst DEFAULT_DATE_OPERATORS = [DATE_IS, LT, GT, DATE_RANGE]\n\nexport type DateOperatorName = (typeof ALL_DATE_OPERATORS)[number][\"name\"]\n\nconst formatter = new DateFormatter(\n new Intl.DateTimeFormat().resolvedOptions().locale,\n { dateStyle: \"medium\" }\n)\n\nconst formatDate = (iso: string) =>\n formatter.format(parseDate(iso).toDate(getLocalTimeZone()))\n\nconst toDateValue = (date: DatePickerDateValue) =>\n typeof date === \"string\" ? parseDate(date) : date\n\nfunction earlier(a?: DatePickerDateValue, b?: DatePickerDateValue) {\n if (a === undefined || b === undefined) return a ?? b\n return toDateValue(a).compare(toDateValue(b)) <= 0 ? a : b\n}\n\nfunction later(a?: DatePickerDateValue, b?: DatePickerDateValue) {\n if (a === undefined || b === undefined) return a ?? b\n return toDateValue(a).compare(toDateValue(b)) >= 0 ? a : b\n}\n\n/** Inclusive bounds on the dates the filter's pickers allow. */\nexport interface DateLimits {\n /** Latest selectable date, as a `DateValue` or ISO date string. */\n max?: DatePickerDateValue\n /** Earliest selectable date, as a `DateValue` or ISO date string. */\n min?: DatePickerDateValue\n}\n\n/**\n * The pickers only flag typed dates outside the limits as invalid, so the\n * editors clear the value rather than commit them.\n */\nfunction toValidDate(date: DateValue | null, { max, min }: DateLimits) {\n if (!date) return undefined\n const isWithinLimits =\n (min === undefined || date.compare(toDateValue(min)) >= 0) &&\n (max === undefined || date.compare(toDateValue(max)) <= 0)\n return isWithinLimits ? date.toString() : undefined\n}\n\nexport function dateFilter({\n excludes,\n includes,\n max,\n min,\n ...config\n}: FilterItemConfig<DateOperatorName> & DateLimits): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new DateActiveFilter(\n filter,\n operator,\n activeFilter.value as DateFilterValue,\n { max, min }\n ),\n operators: resolveOperators(ALL_DATE_OPERATORS, {\n default: DEFAULT_DATE_OPERATORS,\n excludes,\n includes,\n }),\n }\n return filter\n}\n\nclass DateActiveFilter extends ActiveFilterInstance<DateFilterValue> {\n constructor(\n filter: FilterNodeItem,\n operator: Operator,\n value: DateFilterValue,\n readonly limits: DateLimits\n ) {\n super(filter, operator, value)\n }\n\n formatValue() {\n if (Array.isArray(this.value)) {\n const [start, end] = this.value\n if (start === undefined || end === undefined) {\n return [start, end].filter((date) => date !== undefined).map(formatDate)\n }\n return [formatDate(start), \"and\", formatDate(end)]\n }\n return this.value === undefined ? \"\" : formatDate(this.value)\n }\n\n renderEditor(onChange: FilterChange) {\n const { label } = this.operator\n\n if (this.operator.inputType.type === \"date-range\") {\n const range: DateRange = Array.isArray(this.value)\n ? this.value\n : [this.value, this.value]\n return (\n <DateRangeEditor\n label={label}\n max={this.limits.max}\n min={this.limits.min}\n value={range}\n onCommit={(value) => {\n const complete =\n value.length === 2 && value.every((v) => v !== undefined)\n onChange({ value }, { complete })\n }}\n />\n )\n }\n const single = Array.isArray(this.value) ? this.value[0] : this.value\n return (\n <DatePicker\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus\n hideLabel\n // Uncontrolled so a typed date outside the limits stays visible\n // (and flagged invalid) after the value is cleared.\n defaultValue={single}\n label={label}\n max={this.limits.max}\n min={this.limits.min}\n onChange={(date) => {\n const value = toValidDate(date, this.limits)\n onChange({ value }, { complete: value !== undefined })\n }}\n />\n )\n }\n}\n\nfunction DateRangeEditor({\n label,\n max,\n min,\n onCommit,\n value: [start, end],\n}: DateLimits & {\n label: string\n onCommit: (value: DateRange) => void\n value: DateRange\n}) {\n const startLimits = { max: earlier(max, end), min }\n const endLimits = { max, min: later(min, start) }\n\n return (\n <Flex align=\"center\" gap={1}>\n <DatePicker\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus\n hideLabel\n defaultValue={start}\n label={`${label} from`}\n max={startLimits.max}\n min={startLimits.min}\n onChange={(date) => onCommit([toValidDate(date, startLimits), end])}\n />\n <div>and</div>\n <DatePicker\n hideLabel\n defaultValue={end}\n label={`${label} to`}\n max={endLimits.max}\n min={endLimits.min}\n onChange={(date) => onCommit([start, toValidDate(date, endLimits)])}\n />\n </Flex>\n )\n}\n"],"names":["DateFormatter","parseDate","getLocalTimeZone","React"],"mappings":";;;;;;;;;AAwBO,MAAM,OAAO,GAAG;AACrB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,IAAI;AACX,IAAA,IAAI,EAAE,IAAI;;AAEL,MAAM,EAAE,GAAG;AAChB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,WAAW;AAClB,IAAA,IAAI,EAAE,IAAI;;AAEL,MAAM,EAAE,GAAG;AAChB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,UAAU;AACjB,IAAA,IAAI,EAAE,IAAI;;AAEL,MAAM,GAAG,GAAG;AACjB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,iBAAiB;AACxB,IAAA,IAAI,EAAE,KAAK;;AAEN,MAAM,GAAG,GAAG;AACjB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,gBAAgB;AACvB,IAAA,IAAI,EAAE,KAAK;;AAEN,MAAM,UAAU,GAAG;AACxB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;AACjC,IAAA,KAAK,EAAE,YAAY;AACnB,IAAA,IAAI,EAAE,SAAS;;AAGjB,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC;AAClE,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,CAAC;AAI5D,MAAM,SAAS,GAAG,IAAIA,yCAAa,CACjC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,EAClD,EAAE,SAAS,EAAE,QAAQ,EAAE,CACxB;AAED,MAAM,UAAU,GAAG,CAAC,GAAW,KAC7B,SAAS,CAAC,MAAM,CAACC,wCAAS,CAAC,GAAG,CAAC,CAAC,MAAM,CAACC,yCAAgB,EAAE,CAAC,CAAC;AAE7D,MAAM,WAAW,GAAG,CAAC,IAAyB,KAC5C,OAAO,IAAI,KAAK,QAAQ,GAAGD,wCAAS,CAAC,IAAI,CAAC,GAAG,IAAI;AAEnD,SAAS,OAAO,CAAC,CAAuB,EAAE,CAAuB,EAAA;AAC/D,IAAA,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC;IACrD,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D;AAEA,SAAS,KAAK,CAAC,CAAuB,EAAE,CAAuB,EAAA;AAC7D,IAAA,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC;IACrD,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D;AAUA;;;AAGG;AACH,SAAS,WAAW,CAAC,IAAsB,EAAE,EAAE,GAAG,EAAE,GAAG,EAAc,EAAA;AACnE,IAAA,IAAI,CAAC,IAAI;AAAE,QAAA,OAAO,SAAS;AAC3B,IAAA,MAAM,cAAc,GAClB,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;AACzD,SAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAC5D,IAAA,OAAO,cAAc,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,SAAS;AACrD;AAEM,SAAU,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,GAAG,EACH,GAAG,MAAM,EACuC,EAAA;AAChD,IAAA,MAAM,MAAM,GAAmB;AAC7B,QAAA,GAAG,MAAM;QACT,0BAA0B,EAAE,CAAC,YAAY,EAAE,QAAQ,KACjD,IAAI,gBAAgB,CAClB,MAAM,EACN,QAAQ,EACR,YAAY,CAAC,KAAwB,EACrC,EAAE,GAAG,EAAE,GAAG,EAAE,CACb;AACH,QAAA,SAAS,EAAE,gBAAgB,CAAC,kBAAkB,EAAE;AAC9C,YAAA,OAAO,EAAE,sBAAsB;YAC/B,QAAQ;YACR,QAAQ;SACT,CAAC;KACH;AACD,IAAA,OAAO,MAAM;AACf;AAEA,MAAM,gBAAiB,SAAQ,oBAAqC,CAAA;AAKvD,IAAA,MAAA;AAJX,IAAA,WAAA,CACE,MAAsB,EACtB,QAAkB,EAClB,KAAsB,EACb,MAAkB,EAAA;AAE3B,QAAA,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;QAFrB,IAAA,CAAA,MAAM,GAAN,MAAM;IAGjB;IAEA,WAAW,GAAA;QACT,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC7B,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK;YAC/B,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE;gBAC5C,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC;YAC1E;AACA,YAAA,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;QACpD;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;IAC/D;AAEA,IAAA,YAAY,CAAC,QAAsB,EAAA;AACjC,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,QAAQ;QAE/B,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,YAAY,EAAE;YACjD,MAAM,KAAK,GAAc,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK;kBAC7C,IAAI,CAAC;kBACL,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;AAC5B,YAAA,QACEE,cAAA,CAAA,aAAA,CAAC,eAAe,EAAA,EACd,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EACpB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EACpB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,KAAK,KAAI;oBAClB,MAAM,QAAQ,GACZ,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;oBAC3D,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;gBACnC,CAAC,EAAA,CACD;QAEN;QACA,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK;QACrE,QACEA,6BAAC;;;;AAEC,YAAA,SAAS,QACT,SAAS,EAAA,IAAA;;;AAGT,YAAA,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EACpB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EACpB,QAAQ,EAAE,CAAC,IAAI,KAAI;gBACjB,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;AAC5C,gBAAA,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACxD,CAAC,EAAA,CACD;IAEN;AACD;AAED,SAAS,eAAe,CAAC,EACvB,KAAK,EACL,GAAG,EACH,GAAG,EACH,QAAQ,EACR,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,GAKpB,EAAA;AACC,IAAA,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE;AACnD,IAAA,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE;IAEjD,QACEA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EAAC,KAAK,EAAC,QAAQ,EAAC,GAAG,EAAE,CAAC,EAAA;AACzB,QAAAA,cAAA,CAAA,aAAA,CAAC;;;;YAEC,SAAS,EAAA,IAAA,EACT,SAAS,EAAA,IAAA,EACT,YAAY,EAAE,KAAK,EACnB,KAAK,EAAE,CAAA,EAAG,KAAK,CAAA,KAAA,CAAO,EACtB,GAAG,EAAE,WAAW,CAAC,GAAG,EACpB,GAAG,EAAE,WAAW,CAAC,GAAG,EACpB,QAAQ,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC,EAAA,CACnE;QACFA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,IAAA,EAAA,KAAA,CAAc;QACdA,cAAA,CAAA,aAAA,CAAC,UAAU,IACT,SAAS,EAAA,IAAA,EACT,YAAY,EAAE,GAAG,EACjB,KAAK,EAAE,CAAA,EAAG,KAAK,CAAA,GAAA,CAAK,EACpB,GAAG,EAAE,SAAS,CAAC,GAAG,EAClB,GAAG,EAAE,SAAS,CAAC,GAAG,EAClB,QAAQ,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAA,CACnE,CACG;AAEX;;;;"}
@@ -82,8 +82,11 @@ declare const ALL_NUMBER_OPERATORS: ({
82
82
  export type NumberOperatorName = (typeof ALL_NUMBER_OPERATORS)[number]["name"];
83
83
  /** Constraints applied to every input of the filter, including both sides of a range. */
84
84
  export interface NumberConstraints {
85
+ /** Highest value allowed. Typed values above it are clamped. */
85
86
  max?: number;
87
+ /** Lowest value allowed. Typed values below it are clamped. */
86
88
  min?: number;
89
+ /** Increment for the stepper buttons and arrow keys. Typed values snap to it. */
87
90
  step?: number;
88
91
  }
89
92
  export declare function numberFilter({ excludes, includes, max, min, step, ...config }: FilterItemConfig<NumberOperatorName> & NumberConstraints): FilterNodeItem;
@@ -1 +1 @@
1
- {"version":3,"file":"numberFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/numberFilter.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAGtB,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEzD,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,YAAY;;;;;;CAII,CAAA;AAE7B,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAuC,CAAA;AAGjE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9E,yFAAyF;AACzF,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,GAAG,EACH,IAAI,EACJ,GAAG,MAAM,EACV,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,GAAG,iBAAiB,GAAG,cAAc,CAiB3E"}
1
+ {"version":3,"file":"numberFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/numberFilter.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAGtB,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEzD,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,YAAY;;;;;;CAII,CAAA;AAE7B,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAuC,CAAA;AAGjE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9E,yFAAyF;AACzF,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,GAAG,EACH,IAAI,EACJ,GAAG,MAAM,EACV,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,GAAG,iBAAiB,GAAG,cAAc,CAiB3E"}
@@ -1,6 +1,6 @@
1
1
  import { Flex } from '../flex/Flex.js';
2
2
  import { NumberStepper } from '../number-stepper/NumberStepper.js';
3
- import React__default, { useRef } from 'react';
3
+ import React__default, { useRef, useState } from 'react';
4
4
  import { ActiveFilterInstance } from './ActiveFilterInstance.js';
5
5
  import { resolveOperators } from './resolveOperators.js';
6
6
 
@@ -79,11 +79,22 @@ class NumberActiveFilter extends ActiveFilterInstance {
79
79
  return (React__default.createElement(NumberEditor, { key: name, constraints: this.constraints, labels: labels, values: initialValues, onCommit: (committed) => onChange({ value: toValue(committed) }, { complete: committed.every((value) => value !== undefined) }) }));
80
80
  }
81
81
  }
82
+ function lower(a, b) {
83
+ if (a === undefined || b === undefined)
84
+ return a ?? b;
85
+ return Math.min(a, b);
86
+ }
87
+ function higher(a, b) {
88
+ if (a === undefined || b === undefined)
89
+ return a ?? b;
90
+ return Math.max(a, b);
91
+ }
82
92
  // React Aria parses typed text in its own blur and Enter handlers, after ours,
83
93
  // so parsed values go in a ref and commit from the wrapper's blur (which
84
94
  // bubbles after parsing) or Enter's keyup.
85
95
  function NumberEditor({ constraints, labels, onCommit, values: initialValues, }) {
86
96
  const values = useRef(initialValues);
97
+ const [[start, end], setRange] = useState(initialValues);
87
98
  const lastCommitted = useRef(initialValues);
88
99
  const shouldCommitOnKeyUp = useRef(false);
89
100
  const commit = () => {
@@ -103,10 +114,11 @@ function NumberEditor({ constraints, labels, onCommit, values: initialValues, })
103
114
  // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices
104
115
  , {
105
116
  // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices
106
- autoFocus: index === 0, defaultValue: initialValues[index], ...constraints, hideLabel: true, label: label, onChange: (value) => {
117
+ autoFocus: index === 0, defaultValue: initialValues[index], ...constraints, hideLabel: true, label: label, max: index === 0 ? lower(constraints.max, end) : constraints.max, min: index === 1 ? higher(constraints.min, start) : constraints.min, onChange: (value) => {
107
118
  const next = [...values.current];
108
119
  next[index] = Number.isNaN(value) ? undefined : value;
109
120
  values.current = next;
121
+ setRange(next);
110
122
  }, onKeyDown: (e) => {
111
123
  shouldCommitOnKeyUp.current =
112
124
  e.key === "Enter" && !e.nativeEvent.isComposing;
@@ -1 +1 @@
1
- {"version":3,"file":"numberFilter.js","sources":["../../../src/components/DataTable/numberFilter.tsx"],"sourcesContent":["import { Flex } from \"@components/flex\"\nimport {\n NumberStepper,\n type NumberStepperElementProps,\n} from \"@components/number-stepper\"\nimport React, { useRef } from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\nexport type NumberFilterValue = number | [number, number]\n\nexport const GTE = {\n inputType: { type: \"number\" },\n label: \">=\",\n name: \"gte\",\n} as const satisfies Operator\nexport const GT = {\n inputType: { type: \"number\" },\n label: \">\",\n name: \"gt\",\n} as const satisfies Operator\nexport const LT = {\n inputType: { type: \"number\" },\n label: \"<\",\n name: \"lt\",\n} as const satisfies Operator\nexport const EQ = {\n inputType: { type: \"number\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const LTE = {\n inputType: { type: \"number\" },\n label: \"<=\",\n name: \"lte\",\n} as const satisfies Operator\nexport const NUMBER_RANGE = {\n inputType: { type: \"number-range\" },\n label: \"between\",\n name: \"between\",\n} as const satisfies Operator\n\nconst ALL_NUMBER_OPERATORS = [EQ, GT, GTE, LT, LTE, NUMBER_RANGE]\nconst DEFAULT_NUMBER_OPERATORS = [GTE, LTE, NUMBER_RANGE]\n\nexport type NumberOperatorName = (typeof ALL_NUMBER_OPERATORS)[number][\"name\"]\n\n/** Constraints applied to every input of the filter, including both sides of a range. */\nexport interface NumberConstraints {\n max?: number\n min?: number\n step?: number\n}\n\nexport function numberFilter({\n excludes,\n includes,\n max,\n min,\n step,\n ...config\n}: FilterItemConfig<NumberOperatorName> & NumberConstraints): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new NumberActiveFilter(\n filter,\n operator,\n activeFilter.value as NumberFilterValue,\n { max, min, step }\n ),\n operators: resolveOperators(ALL_NUMBER_OPERATORS, {\n default: DEFAULT_NUMBER_OPERATORS,\n excludes,\n includes,\n }),\n }\n return filter\n}\n\ntype NumberInputConstraints = Pick<\n NumberStepperElementProps,\n \"max\" | \"min\" | \"step\"\n>\n\nclass NumberActiveFilter extends ActiveFilterInstance<NumberFilterValue> {\n constructor(\n filter: FilterNodeItem,\n operator: Operator,\n value: NumberFilterValue,\n readonly constraints: NumberInputConstraints\n ) {\n super(filter, operator, value)\n }\n\n formatValue() {\n const formatter = new Intl.NumberFormat()\n return [this.value]\n .flat()\n .filter((value) => value !== undefined)\n .map((value) => formatter.format(value))\n .join(\" and \")\n }\n\n renderEditor(onChange: FilterChange) {\n const { inputType, label, name } = this.operator\n const [start, end] = [this.value].flat()\n const { initialValues, labels, toValue } =\n inputType.type === \"number-range\"\n ? {\n initialValues: [start, end],\n labels: [`${label} from`, `${label} to`],\n toValue: (committed: NumberInputValue[]) => committed,\n }\n : {\n initialValues: [start],\n labels: [label],\n toValue: (committed: NumberInputValue[]) => committed[0],\n }\n return (\n <NumberEditor\n key={name}\n constraints={this.constraints}\n labels={labels}\n values={initialValues}\n onCommit={(committed) =>\n onChange(\n { value: toValue(committed) },\n { complete: committed.every((value) => value !== undefined) }\n )\n }\n />\n )\n }\n}\n\ntype NumberInputValue = number | undefined\n\n// React Aria parses typed text in its own blur and Enter handlers, after ours,\n// so parsed values go in a ref and commit from the wrapper's blur (which\n// bubbles after parsing) or Enter's keyup.\nfunction NumberEditor({\n constraints,\n labels,\n onCommit,\n values: initialValues,\n}: {\n constraints: NumberInputConstraints\n labels: string[]\n onCommit: (values: NumberInputValue[]) => void\n values: NumberInputValue[]\n}) {\n const values = useRef(initialValues)\n const lastCommitted = useRef(initialValues)\n const shouldCommitOnKeyUp = useRef(false)\n const commit = () => {\n lastCommitted.current = values.current\n onCommit(values.current)\n }\n const changed = () =>\n values.current.some(\n (value, index) => value !== lastCommitted.current[index]\n )\n const isRange = labels.length > 1\n return (\n <Flex\n align=\"center\"\n // Popover content aligns to start; stretch so both inputs fit\n alignSelf={isRange ? \"stretch\" : undefined}\n className={isRange ? \"tds-data-table-filters-number-range\" : undefined}\n gap={1}\n onBlur={() => {\n if (changed()) commit()\n }}\n >\n {labels.map((label, index) => (\n <React.Fragment key={label}>\n {index > 0 && <span>and</span>}\n <NumberStepper\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus={index === 0}\n defaultValue={initialValues[index]}\n {...constraints}\n hideLabel\n label={label}\n onChange={(value) => {\n const next = [...values.current]\n next[index] = Number.isNaN(value) ? undefined : value\n values.current = next\n }}\n onKeyDown={(e) => {\n shouldCommitOnKeyUp.current =\n e.key === \"Enter\" && !e.nativeEvent.isComposing\n }}\n onKeyUp={(e) => {\n if (e.key !== \"Enter\" || !shouldCommitOnKeyUp.current) return\n shouldCommitOnKeyUp.current = false\n commit()\n }}\n />\n </React.Fragment>\n ))}\n </Flex>\n )\n}\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"numberFilter.js","sources":["../../../src/components/DataTable/numberFilter.tsx"],"sourcesContent":["import { Flex } from \"@components/flex\"\nimport {\n NumberStepper,\n type NumberStepperElementProps,\n} from \"@components/number-stepper\"\nimport React, { useRef, useState } from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\nexport type NumberFilterValue = number | [number, number]\n\nexport const GTE = {\n inputType: { type: \"number\" },\n label: \">=\",\n name: \"gte\",\n} as const satisfies Operator\nexport const GT = {\n inputType: { type: \"number\" },\n label: \">\",\n name: \"gt\",\n} as const satisfies Operator\nexport const LT = {\n inputType: { type: \"number\" },\n label: \"<\",\n name: \"lt\",\n} as const satisfies Operator\nexport const EQ = {\n inputType: { type: \"number\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const LTE = {\n inputType: { type: \"number\" },\n label: \"<=\",\n name: \"lte\",\n} as const satisfies Operator\nexport const NUMBER_RANGE = {\n inputType: { type: \"number-range\" },\n label: \"between\",\n name: \"between\",\n} as const satisfies Operator\n\nconst ALL_NUMBER_OPERATORS = [EQ, GT, GTE, LT, LTE, NUMBER_RANGE]\nconst DEFAULT_NUMBER_OPERATORS = [GTE, LTE, NUMBER_RANGE]\n\nexport type NumberOperatorName = (typeof ALL_NUMBER_OPERATORS)[number][\"name\"]\n\n/** Constraints applied to every input of the filter, including both sides of a range. */\nexport interface NumberConstraints {\n /** Highest value allowed. Typed values above it are clamped. */\n max?: number\n /** Lowest value allowed. Typed values below it are clamped. */\n min?: number\n /** Increment for the stepper buttons and arrow keys. Typed values snap to it. */\n step?: number\n}\n\nexport function numberFilter({\n excludes,\n includes,\n max,\n min,\n step,\n ...config\n}: FilterItemConfig<NumberOperatorName> & NumberConstraints): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new NumberActiveFilter(\n filter,\n operator,\n activeFilter.value as NumberFilterValue,\n { max, min, step }\n ),\n operators: resolveOperators(ALL_NUMBER_OPERATORS, {\n default: DEFAULT_NUMBER_OPERATORS,\n excludes,\n includes,\n }),\n }\n return filter\n}\n\ntype NumberInputConstraints = Pick<\n NumberStepperElementProps,\n \"max\" | \"min\" | \"step\"\n>\n\nclass NumberActiveFilter extends ActiveFilterInstance<NumberFilterValue> {\n constructor(\n filter: FilterNodeItem,\n operator: Operator,\n value: NumberFilterValue,\n readonly constraints: NumberInputConstraints\n ) {\n super(filter, operator, value)\n }\n\n formatValue() {\n const formatter = new Intl.NumberFormat()\n return [this.value]\n .flat()\n .filter((value) => value !== undefined)\n .map((value) => formatter.format(value))\n .join(\" and \")\n }\n\n renderEditor(onChange: FilterChange) {\n const { inputType, label, name } = this.operator\n const [start, end] = [this.value].flat()\n const { initialValues, labels, toValue } =\n inputType.type === \"number-range\"\n ? {\n initialValues: [start, end],\n labels: [`${label} from`, `${label} to`],\n toValue: (committed: NumberInputValue[]) => committed,\n }\n : {\n initialValues: [start],\n labels: [label],\n toValue: (committed: NumberInputValue[]) => committed[0],\n }\n return (\n <NumberEditor\n key={name}\n constraints={this.constraints}\n labels={labels}\n values={initialValues}\n onCommit={(committed) =>\n onChange(\n { value: toValue(committed) },\n { complete: committed.every((value) => value !== undefined) }\n )\n }\n />\n )\n }\n}\n\ntype NumberInputValue = number | undefined\n\nfunction lower(a: NumberInputValue, b: NumberInputValue) {\n if (a === undefined || b === undefined) return a ?? b\n return Math.min(a, b)\n}\n\nfunction higher(a: NumberInputValue, b: NumberInputValue) {\n if (a === undefined || b === undefined) return a ?? b\n return Math.max(a, b)\n}\n\n// React Aria parses typed text in its own blur and Enter handlers, after ours,\n// so parsed values go in a ref and commit from the wrapper's blur (which\n// bubbles after parsing) or Enter's keyup.\nfunction NumberEditor({\n constraints,\n labels,\n onCommit,\n values: initialValues,\n}: {\n constraints: NumberInputConstraints\n labels: string[]\n onCommit: (values: NumberInputValue[]) => void\n values: NumberInputValue[]\n}) {\n const values = useRef(initialValues)\n const [[start, end], setRange] = useState(initialValues)\n const lastCommitted = useRef(initialValues)\n const shouldCommitOnKeyUp = useRef(false)\n const commit = () => {\n lastCommitted.current = values.current\n onCommit(values.current)\n }\n const changed = () =>\n values.current.some(\n (value, index) => value !== lastCommitted.current[index]\n )\n const isRange = labels.length > 1\n return (\n <Flex\n align=\"center\"\n // Popover content aligns to start; stretch so both inputs fit\n alignSelf={isRange ? \"stretch\" : undefined}\n className={isRange ? \"tds-data-table-filters-number-range\" : undefined}\n gap={1}\n onBlur={() => {\n if (changed()) commit()\n }}\n >\n {labels.map((label, index) => (\n <React.Fragment key={label}>\n {index > 0 && <span>and</span>}\n <NumberStepper\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus={index === 0}\n defaultValue={initialValues[index]}\n {...constraints}\n hideLabel\n label={label}\n max={index === 0 ? lower(constraints.max, end) : constraints.max}\n min={index === 1 ? higher(constraints.min, start) : constraints.min}\n onChange={(value) => {\n const next = [...values.current]\n next[index] = Number.isNaN(value) ? undefined : value\n values.current = next\n setRange(next)\n }}\n onKeyDown={(e) => {\n shouldCommitOnKeyUp.current =\n e.key === \"Enter\" && !e.nativeEvent.isComposing\n }}\n onKeyUp={(e) => {\n if (e.key !== \"Enter\" || !shouldCommitOnKeyUp.current) return\n shouldCommitOnKeyUp.current = false\n commit()\n }}\n />\n </React.Fragment>\n ))}\n </Flex>\n )\n}\n"],"names":["React"],"mappings":"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"}
@@ -2,7 +2,9 @@ import type { FilterItemConfig, FilterNodeItem, FilterNodeScoped, ScopeOption }
2
2
  export type ScopedFilterOptions = ScopeOption[];
3
3
  export type ScopedFilterOptionsLoader = () => Promise<ScopedFilterOptions> | ScopedFilterOptions;
4
4
  export type ScopedFilterConfig = Omit<FilterItemConfig, "excludes" | "includes"> & Pick<FilterNodeScoped, "allowMultiplePerScope"> & {
5
+ /** The filter applied within the chosen scope, usually a `collectionFilter`. */
5
6
  filter: FilterNodeItem;
7
+ /** The scopes to pick from, or a function that loads them when the editor opens. */
6
8
  options: ScopedFilterOptions | ScopedFilterOptionsLoader;
7
9
  };
8
10
  export declare function scopedFilter({ allowMultiple, filter: scopeFilter, options, ...config }: ScopedFilterConfig): FilterNodeScoped;
@@ -1 +1 @@
1
- {"version":3,"file":"scopedFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/scopedFilter.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAEhB,WAAW,EACZ,MAAM,eAAe,CAAA;AAWtB,MAAM,MAAM,mBAAmB,GAAG,WAAW,EAAE,CAAA;AAE/C,MAAM,MAAM,yBAAyB,GAAG,MACpC,OAAO,CAAC,mBAAmB,CAAC,GAC5B,mBAAmB,CAAA;AAEvB,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,gBAAgB,EAChB,UAAU,GAAG,UAAU,CACxB,GACC,IAAI,CAAC,gBAAgB,EAAE,uBAAuB,CAAC,GAAG;IAChD,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,mBAAmB,GAAG,yBAAyB,CAAA;CACzD,CAAA;AAEH,wBAAgB,YAAY,CAAC,EAC3B,aAAoB,EACpB,MAAM,EAAE,WAAW,EACnB,OAAO,EACP,GAAG,MAAM,EACV,EAAE,kBAAkB,GAAG,gBAAgB,CAYvC"}
1
+ {"version":3,"file":"scopedFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/scopedFilter.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAEhB,WAAW,EACZ,MAAM,eAAe,CAAA;AAWtB,MAAM,MAAM,mBAAmB,GAAG,WAAW,EAAE,CAAA;AAE/C,MAAM,MAAM,yBAAyB,GAAG,MACpC,OAAO,CAAC,mBAAmB,CAAC,GAC5B,mBAAmB,CAAA;AAEvB,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,gBAAgB,EAChB,UAAU,GAAG,UAAU,CACxB,GACC,IAAI,CAAC,gBAAgB,EAAE,uBAAuB,CAAC,GAAG;IAChD,gFAAgF;IAChF,MAAM,EAAE,cAAc,CAAA;IACtB,oFAAoF;IACpF,OAAO,EAAE,mBAAmB,GAAG,yBAAyB,CAAA;CACzD,CAAA;AAEH,wBAAgB,YAAY,CAAC,EAC3B,aAAoB,EACpB,MAAM,EAAE,WAAW,EACnB,OAAO,EACP,GAAG,MAAM,EACV,EAAE,kBAAkB,GAAG,gBAAgB,CAYvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"scopedFilter.js","sources":["../../../src/components/DataTable/scopedFilter.tsx"],"sourcesContent":["import { Select } from \"@components/select\"\nimport React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport { LoadError, Loading } from \"./CollectionEditorsLazy\"\nimport { useHasFilterInstancesChecker } from \"./FilterContext\"\nimport type {\n ActiveFilter,\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n FilterNodeScoped,\n Operator,\n ScopeOption,\n} from \"./FilterTypes\"\nimport { OperatorSelect } from \"./OperatorSelect\"\nimport { useLazyOptions } from \"./useLazyOptions\"\nimport { getDefaultOperatorName, isEmptyValue } from \"./utils\"\n\nconst SCOPED_DEFAULT = {\n inputType: { type: \"scoped\" },\n label: \"\",\n name: \"scoped\",\n} as const satisfies Operator\n\nexport type ScopedFilterOptions = ScopeOption[]\n\nexport type ScopedFilterOptionsLoader = () =>\n | Promise<ScopedFilterOptions>\n | ScopedFilterOptions\n\nexport type ScopedFilterConfig = Omit<\n FilterItemConfig,\n \"excludes\" | \"includes\"\n> &\n Pick<FilterNodeScoped, \"allowMultiplePerScope\"> & {\n filter: FilterNodeItem\n options: ScopedFilterOptions | ScopedFilterOptionsLoader\n }\n\nexport function scopedFilter({\n allowMultiple = true,\n filter: scopeFilter,\n options,\n ...config\n}: ScopedFilterConfig): FilterNodeScoped {\n const loadOptions = typeof options === \"function\" ? options : undefined\n const filter: FilterNodeScoped = {\n ...config,\n allowMultiple,\n createActiveFilterInstance: (activeFilter, operator) =>\n new ScopedActiveFilter(filter, operator, activeFilter, loadOptions),\n operators: [SCOPED_DEFAULT],\n options: typeof options === \"function\" ? [] : options,\n scopeFilter,\n }\n return filter\n}\n\nfunction defaultScopedActiveFilter(\n parentName: string,\n scopeFilter: FilterNodeItem,\n option: ScopeOption\n): ActiveFilter {\n return {\n label: undefined,\n name: parentName,\n operator: getDefaultOperatorName(scopeFilter),\n scope: option.value,\n value: undefined,\n }\n}\n\nclass ScopedActiveFilter extends ActiveFilterInstance<unknown> {\n private readonly activeFilter: ActiveFilter\n\n constructor(\n private readonly scopedFilter: FilterNodeScoped,\n operator: Operator,\n activeFilter: ActiveFilter,\n private readonly loadOptions: ScopedFilterOptionsLoader | undefined\n ) {\n super(scopedFilter, operator, activeFilter.value)\n this.activeFilter = activeFilter\n }\n\n private get scopeLabel() {\n const { scope, scopeLabel } = this.activeFilter\n if (scope === undefined) return undefined\n if (this.loadOptions) return scopeLabel ?? scope\n return this.scopedFilter.options.find(({ value }) => value === scope)?.label\n }\n\n private get scopeFilterInstance() {\n return this.scopedFilter.scopeFilter.createActiveFilterInstance(\n this.activeFilter,\n this.operator\n )\n }\n\n toSegments() {\n const { scopeLabel } = this\n if (!scopeLabel) return [this.filter.label]\n\n if (this.activeFilter.value === undefined)\n return [this.filter.label, scopeLabel]\n\n const SKIP_SCOPE_FILTER_LABEL = 1\n return [\n this.filter.label,\n scopeLabel,\n ...this.scopeFilterInstance.toSegments().slice(SKIP_SCOPE_FILTER_LABEL),\n ]\n }\n\n formatValue() {\n if (!this.scopeLabel) return []\n return this.scopeFilterInstance.formatValue()\n }\n\n renderEditor(onChange: FilterChange) {\n const props = {\n activeFilter: this.activeFilter,\n allowMultiplePerScope: this.scopedFilter.allowMultiplePerScope,\n label: this.filter.label,\n onChange,\n scopeFilter: this.scopedFilter.scopeFilter,\n scopeFilterInstance:\n this.activeFilter.scope === undefined\n ? undefined\n : this.scopeFilterInstance,\n }\n\n if (this.loadOptions)\n return <LazyScopeEditor {...props} loadOptions={this.loadOptions} />\n\n return <ScopeEditor {...props} options={this.scopedFilter.options} />\n }\n}\n\ntype ScopeEditorProps = {\n activeFilter: ActiveFilter\n allowMultiplePerScope: boolean | undefined\n label: string\n onChange: FilterChange\n scopeFilter: FilterNodeItem\n scopeFilterInstance: ActiveFilterInstance | undefined\n}\n\nfunction LazyScopeEditor({\n loadOptions,\n ...props\n}: ScopeEditorProps & { loadOptions: ScopedFilterOptionsLoader }) {\n const { error, loading, options } = useLazyOptions(loadOptions)\n if (loading) return <Loading />\n if (error) return <LoadError />\n\n const { activeFilter } = props\n const isScopeMissing =\n activeFilter.scope !== undefined &&\n !options.some(({ value }) => value === activeFilter.scope)\n\n const reset = isScopeMissing && {\n activeFilter: {\n name: activeFilter.name,\n operator: SCOPED_DEFAULT.name,\n value: undefined,\n },\n scopeFilterInstance: undefined,\n }\n\n return <ScopeEditor {...props} {...reset} options={options} storeScopeLabel />\n}\n\nfunction ScopeEditor({\n activeFilter,\n allowMultiplePerScope,\n label,\n onChange,\n options,\n scopeFilter,\n scopeFilterInstance,\n storeScopeLabel = false,\n}: ScopeEditorProps & {\n options: ScopedFilterOptions\n /** Lazy scopes only: the chip can't look the label up, so it's stored. */\n storeScopeLabel?: boolean\n}) {\n const remembered = React.useRef<\n Record<string, Pick<ActiveFilter, \"label\" | \"operator\" | \"value\">>\n >({})\n const hasFilterInstances = useHasFilterInstancesChecker()\n const scopeOptions = allowMultiplePerScope\n ? options\n : options.map((option) => ({\n ...option,\n disabled:\n option.value !== activeFilter.scope &&\n hasFilterInstances(activeFilter.name, option.value),\n }))\n\n return (\n <>\n <Select\n hideLabel\n label={label}\n options={scopeOptions}\n placeholder={`Select a ${label.toLowerCase()}`}\n value={activeFilter.scope ?? \"\"}\n onChange={(e) => {\n const { label: valueLabel, operator, scope, value } = activeFilter\n if (scope !== undefined) {\n if (isEmptyValue(value)) {\n delete remembered.current[scope]\n } else {\n remembered.current[scope] = {\n operator,\n value,\n ...(valueLabel !== undefined && { label: valueLabel }),\n }\n }\n }\n const next = options.find((option) => option.value === e.target.value)\n if (!next) return\n const restored = remembered.current[next.value]\n const scoped = {\n ...defaultScopedActiveFilter(activeFilter.name, scopeFilter, next),\n ...(storeScopeLabel && { scopeLabel: next.label }),\n ...restored,\n }\n onChange(scoped, { complete: !isEmptyValue(scoped.value) })\n }}\n />\n {scopeFilterInstance && (\n <SelectedScopeEditor\n activeFilter={activeFilter}\n instance={scopeFilterInstance}\n scopeFilter={scopeFilter}\n onChange={onChange}\n />\n )}\n </>\n )\n}\n\nfunction SelectedScopeEditor({\n activeFilter,\n instance,\n scopeFilter,\n onChange,\n}: {\n activeFilter: ActiveFilter\n instance: ActiveFilterInstance\n onChange: FilterChange\n scopeFilter: FilterNodeItem\n}) {\n return (\n <>\n <OperatorSelect\n operator={instance.operator}\n relatedFilter={scopeFilter}\n updateActiveFilter={(updates) => {\n if (updates.operator && updates.operator !== activeFilter.operator) {\n onChange({ ...updates, value: undefined }, { complete: false })\n return\n }\n onChange(updates, { complete: false })\n }}\n />\n <React.Fragment key={`${activeFilter.scope}:${instance.operator.name}`}>\n {instance.renderEditor(onChange)}\n </React.Fragment>\n </>\n )\n}\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"scopedFilter.js","sources":["../../../src/components/DataTable/scopedFilter.tsx"],"sourcesContent":["import { Select } from \"@components/select\"\nimport React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport { LoadError, Loading } from \"./CollectionEditorsLazy\"\nimport { useHasFilterInstancesChecker } from \"./FilterContext\"\nimport type {\n ActiveFilter,\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n FilterNodeScoped,\n Operator,\n ScopeOption,\n} from \"./FilterTypes\"\nimport { OperatorSelect } from \"./OperatorSelect\"\nimport { useLazyOptions } from \"./useLazyOptions\"\nimport { getDefaultOperatorName, isEmptyValue } from \"./utils\"\n\nconst SCOPED_DEFAULT = {\n inputType: { type: \"scoped\" },\n label: \"\",\n name: \"scoped\",\n} as const satisfies Operator\n\nexport type ScopedFilterOptions = ScopeOption[]\n\nexport type ScopedFilterOptionsLoader = () =>\n | Promise<ScopedFilterOptions>\n | ScopedFilterOptions\n\nexport type ScopedFilterConfig = Omit<\n FilterItemConfig,\n \"excludes\" | \"includes\"\n> &\n Pick<FilterNodeScoped, \"allowMultiplePerScope\"> & {\n /** The filter applied within the chosen scope, usually a `collectionFilter`. */\n filter: FilterNodeItem\n /** The scopes to pick from, or a function that loads them when the editor opens. */\n options: ScopedFilterOptions | ScopedFilterOptionsLoader\n }\n\nexport function scopedFilter({\n allowMultiple = true,\n filter: scopeFilter,\n options,\n ...config\n}: ScopedFilterConfig): FilterNodeScoped {\n const loadOptions = typeof options === \"function\" ? options : undefined\n const filter: FilterNodeScoped = {\n ...config,\n allowMultiple,\n createActiveFilterInstance: (activeFilter, operator) =>\n new ScopedActiveFilter(filter, operator, activeFilter, loadOptions),\n operators: [SCOPED_DEFAULT],\n options: typeof options === \"function\" ? [] : options,\n scopeFilter,\n }\n return filter\n}\n\nfunction defaultScopedActiveFilter(\n parentName: string,\n scopeFilter: FilterNodeItem,\n option: ScopeOption\n): ActiveFilter {\n return {\n label: undefined,\n name: parentName,\n operator: getDefaultOperatorName(scopeFilter),\n scope: option.value,\n value: undefined,\n }\n}\n\nclass ScopedActiveFilter extends ActiveFilterInstance<unknown> {\n private readonly activeFilter: ActiveFilter\n\n constructor(\n private readonly scopedFilter: FilterNodeScoped,\n operator: Operator,\n activeFilter: ActiveFilter,\n private readonly loadOptions: ScopedFilterOptionsLoader | undefined\n ) {\n super(scopedFilter, operator, activeFilter.value)\n this.activeFilter = activeFilter\n }\n\n private get scopeLabel() {\n const { scope, scopeLabel } = this.activeFilter\n if (scope === undefined) return undefined\n if (this.loadOptions) return scopeLabel ?? scope\n return this.scopedFilter.options.find(({ value }) => value === scope)?.label\n }\n\n private get scopeFilterInstance() {\n return this.scopedFilter.scopeFilter.createActiveFilterInstance(\n this.activeFilter,\n this.operator\n )\n }\n\n toSegments() {\n const { scopeLabel } = this\n if (!scopeLabel) return [this.filter.label]\n\n if (this.activeFilter.value === undefined)\n return [this.filter.label, scopeLabel]\n\n const SKIP_SCOPE_FILTER_LABEL = 1\n return [\n this.filter.label,\n scopeLabel,\n ...this.scopeFilterInstance.toSegments().slice(SKIP_SCOPE_FILTER_LABEL),\n ]\n }\n\n formatValue() {\n if (!this.scopeLabel) return []\n return this.scopeFilterInstance.formatValue()\n }\n\n renderEditor(onChange: FilterChange) {\n const props = {\n activeFilter: this.activeFilter,\n allowMultiplePerScope: this.scopedFilter.allowMultiplePerScope,\n label: this.filter.label,\n onChange,\n scopeFilter: this.scopedFilter.scopeFilter,\n scopeFilterInstance:\n this.activeFilter.scope === undefined\n ? undefined\n : this.scopeFilterInstance,\n }\n\n if (this.loadOptions)\n return <LazyScopeEditor {...props} loadOptions={this.loadOptions} />\n\n return <ScopeEditor {...props} options={this.scopedFilter.options} />\n }\n}\n\ntype ScopeEditorProps = {\n activeFilter: ActiveFilter\n allowMultiplePerScope: boolean | undefined\n label: string\n onChange: FilterChange\n scopeFilter: FilterNodeItem\n scopeFilterInstance: ActiveFilterInstance | undefined\n}\n\nfunction LazyScopeEditor({\n loadOptions,\n ...props\n}: ScopeEditorProps & { loadOptions: ScopedFilterOptionsLoader }) {\n const { error, loading, options } = useLazyOptions(loadOptions)\n if (loading) return <Loading />\n if (error) return <LoadError />\n\n const { activeFilter } = props\n const isScopeMissing =\n activeFilter.scope !== undefined &&\n !options.some(({ value }) => value === activeFilter.scope)\n\n const reset = isScopeMissing && {\n activeFilter: {\n name: activeFilter.name,\n operator: SCOPED_DEFAULT.name,\n value: undefined,\n },\n scopeFilterInstance: undefined,\n }\n\n return <ScopeEditor {...props} {...reset} options={options} storeScopeLabel />\n}\n\nfunction ScopeEditor({\n activeFilter,\n allowMultiplePerScope,\n label,\n onChange,\n options,\n scopeFilter,\n scopeFilterInstance,\n storeScopeLabel = false,\n}: ScopeEditorProps & {\n options: ScopedFilterOptions\n /** Lazy scopes only: the chip can't look the label up, so it's stored. */\n storeScopeLabel?: boolean\n}) {\n const remembered = React.useRef<\n Record<string, Pick<ActiveFilter, \"label\" | \"operator\" | \"value\">>\n >({})\n const hasFilterInstances = useHasFilterInstancesChecker()\n const scopeOptions = allowMultiplePerScope\n ? options\n : options.map((option) => ({\n ...option,\n disabled:\n option.value !== activeFilter.scope &&\n hasFilterInstances(activeFilter.name, option.value),\n }))\n\n return (\n <>\n <Select\n hideLabel\n label={label}\n options={scopeOptions}\n placeholder={`Select a ${label.toLowerCase()}`}\n value={activeFilter.scope ?? \"\"}\n onChange={(e) => {\n const { label: valueLabel, operator, scope, value } = activeFilter\n if (scope !== undefined) {\n if (isEmptyValue(value)) {\n delete remembered.current[scope]\n } else {\n remembered.current[scope] = {\n operator,\n value,\n ...(valueLabel !== undefined && { label: valueLabel }),\n }\n }\n }\n const next = options.find((option) => option.value === e.target.value)\n if (!next) return\n const restored = remembered.current[next.value]\n const scoped = {\n ...defaultScopedActiveFilter(activeFilter.name, scopeFilter, next),\n ...(storeScopeLabel && { scopeLabel: next.label }),\n ...restored,\n }\n onChange(scoped, { complete: !isEmptyValue(scoped.value) })\n }}\n />\n {scopeFilterInstance && (\n <SelectedScopeEditor\n activeFilter={activeFilter}\n instance={scopeFilterInstance}\n scopeFilter={scopeFilter}\n onChange={onChange}\n />\n )}\n </>\n )\n}\n\nfunction SelectedScopeEditor({\n activeFilter,\n instance,\n scopeFilter,\n onChange,\n}: {\n activeFilter: ActiveFilter\n instance: ActiveFilterInstance\n onChange: FilterChange\n scopeFilter: FilterNodeItem\n}) {\n return (\n <>\n <OperatorSelect\n operator={instance.operator}\n relatedFilter={scopeFilter}\n updateActiveFilter={(updates) => {\n if (updates.operator && updates.operator !== activeFilter.operator) {\n onChange({ ...updates, value: undefined }, { complete: false })\n return\n }\n onChange(updates, { complete: false })\n }}\n />\n <React.Fragment key={`${activeFilter.scope}:${instance.operator.name}`}>\n {instance.renderEditor(onChange)}\n </React.Fragment>\n </>\n )\n}\n"],"names":["React"],"mappings":"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"}