@planningcenter/tapestry 4.6.1 → 4.7.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/components/DataTable/ActiveFilterInstance.d.ts +13 -0
  2. package/dist/components/DataTable/ActiveFilterInstance.d.ts.map +1 -0
  3. package/dist/components/DataTable/ActiveFilterInstance.js +23 -0
  4. package/dist/components/DataTable/ActiveFilterInstance.js.map +1 -0
  5. package/dist/components/DataTable/ActiveFilters.d.ts +3 -4
  6. package/dist/components/DataTable/ActiveFilters.d.ts.map +1 -1
  7. package/dist/components/DataTable/ActiveFilters.js +25 -35
  8. package/dist/components/DataTable/ActiveFilters.js.map +1 -1
  9. package/dist/components/DataTable/DataTable.d.ts +1 -0
  10. package/dist/components/DataTable/DataTable.d.ts.map +1 -1
  11. package/dist/components/DataTable/DataTable.js +12 -2
  12. package/dist/components/DataTable/DataTable.js.map +1 -1
  13. package/dist/components/DataTable/FilterChip.d.ts +26 -0
  14. package/dist/components/DataTable/FilterChip.d.ts.map +1 -0
  15. package/dist/components/DataTable/FilterChip.js +36 -0
  16. package/dist/components/DataTable/FilterChip.js.map +1 -0
  17. package/dist/components/DataTable/FilterContext.d.ts.map +1 -1
  18. package/dist/components/DataTable/FilterContext.js +3 -1
  19. package/dist/components/DataTable/FilterContext.js.map +1 -1
  20. package/dist/components/DataTable/FilterControls.d.ts +8 -2
  21. package/dist/components/DataTable/FilterControls.d.ts.map +1 -1
  22. package/dist/components/DataTable/FilterControls.js +48 -7
  23. package/dist/components/DataTable/FilterControls.js.map +1 -1
  24. package/dist/components/DataTable/FilterTypes.d.ts +14 -1
  25. package/dist/components/DataTable/FilterTypes.d.ts.map +1 -1
  26. package/dist/components/DataTable/OperatorSelect.d.ts +1 -2
  27. package/dist/components/DataTable/OperatorSelect.d.ts.map +1 -1
  28. package/dist/components/DataTable/OperatorSelect.js.map +1 -1
  29. package/dist/components/DataTable/SearchableFilters.d.ts +14 -0
  30. package/dist/components/DataTable/SearchableFilters.d.ts.map +1 -0
  31. package/dist/components/DataTable/SearchableFilters.js +35 -0
  32. package/dist/components/DataTable/SearchableFilters.js.map +1 -0
  33. package/dist/components/DataTable/collectionFilter.d.ts +48 -0
  34. package/dist/components/DataTable/collectionFilter.d.ts.map +1 -0
  35. package/dist/components/DataTable/collectionFilter.js +86 -0
  36. package/dist/components/DataTable/collectionFilter.js.map +1 -0
  37. package/dist/components/DataTable/dateFilter.d.ts +60 -0
  38. package/dist/components/DataTable/dateFilter.d.ts.map +1 -0
  39. package/dist/components/DataTable/dateFilter.js +67 -0
  40. package/dist/components/DataTable/dateFilter.js.map +1 -0
  41. package/dist/components/DataTable/filters.d.ts +5 -0
  42. package/dist/components/DataTable/filters.d.ts.map +1 -0
  43. package/dist/components/DataTable/index.d.ts +4 -0
  44. package/dist/components/DataTable/index.d.ts.map +1 -1
  45. package/dist/components/DataTable/numberFilter.d.ts +46 -0
  46. package/dist/components/DataTable/numberFilter.d.ts.map +1 -0
  47. package/dist/components/DataTable/numberFilter.js +63 -0
  48. package/dist/components/DataTable/numberFilter.js.map +1 -0
  49. package/dist/components/DataTable/resolveOperators.d.ts +7 -0
  50. package/dist/components/DataTable/resolveOperators.d.ts.map +1 -0
  51. package/dist/components/DataTable/resolveOperators.js +11 -0
  52. package/dist/components/DataTable/resolveOperators.js.map +1 -0
  53. package/dist/components/DataTable/textFilter.d.ts +58 -0
  54. package/dist/components/DataTable/textFilter.d.ts.map +1 -0
  55. package/dist/components/DataTable/textFilter.js +49 -0
  56. package/dist/components/DataTable/textFilter.js.map +1 -0
  57. package/dist/components/DataTable/useShelfExpanded.d.ts +6 -0
  58. package/dist/components/DataTable/useShelfExpanded.d.ts.map +1 -0
  59. package/dist/components/DataTable/useShelfExpanded.js +26 -0
  60. package/dist/components/DataTable/useShelfExpanded.js.map +1 -0
  61. package/dist/components/dropdown/Dropdown.d.ts +4 -0
  62. package/dist/components/dropdown/Dropdown.d.ts.map +1 -1
  63. package/dist/components/dropdown/Dropdown.js +4 -0
  64. package/dist/components/dropdown/Dropdown.js.map +1 -1
  65. package/dist/components/input/Input.d.ts +4 -4
  66. package/dist/components/input/Input.d.ts.map +1 -1
  67. package/dist/components/input/Input.js +3 -3
  68. package/dist/components/input/Input.js.map +1 -1
  69. package/dist/components/popover/Popover.d.ts +1 -1
  70. package/dist/components/popover/Popover.js +1 -1
  71. package/dist/components/popover/Popover.js.map +1 -1
  72. package/dist/index.css +89 -1
  73. package/dist/index.css.map +1 -1
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +1 -0
  77. package/dist/index.js.map +1 -1
  78. package/dist/reactRender.css +1292 -1041
  79. package/dist/reactRender.css.map +1 -1
  80. package/dist/reactRenderLegacy.css +1292 -1041
  81. package/dist/reactRenderLegacy.css.map +1 -1
  82. package/dist/unstable.css +3717 -3466
  83. package/dist/unstable.css.map +1 -1
  84. package/dist/unstable.d.ts +0 -1
  85. package/dist/unstable.d.ts.map +1 -1
  86. package/dist/unstable.js +5 -1
  87. package/dist/unstable.js.map +1 -1
  88. package/package.json +2 -2
@@ -0,0 +1,67 @@
1
+ import { DatePicker } from '../date-picker/DatePicker.js';
2
+ import { Flex } from '../flex/Flex.js';
3
+ import { getLocalTimeZone as $ad063034c8620db8$export$aa8b41735afcabd2 } from './../../ext/@internationalized/date/dist/private/queries.js';
4
+ import { parseDate as $58246871e4652552$export$6b862160d295c8e } from './../../ext/@internationalized/date/dist/private/string.js';
5
+ import { DateFormatter as $12a3c853105e5a70$export$ad991b66133851cf } from './../../ext/@internationalized/date/dist/private/DateFormatter.js';
6
+ import React__default from 'react';
7
+ import { ActiveFilterInstance } from './ActiveFilterInstance.js';
8
+ import { resolveOperators } from './resolveOperators.js';
9
+
10
+ const DATE_IS = {
11
+ inputType: { type: "date" },
12
+ label: "is",
13
+ name: "eq",
14
+ };
15
+ const BEFORE = {
16
+ inputType: { type: "date" },
17
+ label: "before",
18
+ name: "before",
19
+ };
20
+ const AFTER = {
21
+ inputType: { type: "date" },
22
+ label: "after",
23
+ name: "after",
24
+ };
25
+ const DATE_RANGE = {
26
+ inputType: { type: "date-range" },
27
+ label: "between",
28
+ name: "date_range",
29
+ };
30
+ const DATE_OPERATORS = [DATE_IS, BEFORE, AFTER, DATE_RANGE];
31
+ const formatter = new $12a3c853105e5a70$export$ad991b66133851cf(new Intl.DateTimeFormat().resolvedOptions().locale, { dateStyle: "medium" });
32
+ const formatDate = (iso) => formatter.format($58246871e4652552$export$6b862160d295c8e(iso).toDate($ad063034c8620db8$export$aa8b41735afcabd2()));
33
+ function dateFilter({ excludes, includes, ...config }) {
34
+ const filter = {
35
+ ...config,
36
+ createActiveFilterInstance: (activeFilter, operator) => new DateActiveFilter(filter, operator, activeFilter.value),
37
+ operators: resolveOperators(DATE_OPERATORS, { excludes, includes }),
38
+ };
39
+ return filter;
40
+ }
41
+ class DateActiveFilter extends ActiveFilterInstance {
42
+ formatValue() {
43
+ return Array.isArray(this.value)
44
+ ? [formatDate(this.value[0]), "and", formatDate(this.value[1])]
45
+ : formatDate(this.value);
46
+ }
47
+ renderEditor(updateActiveFilter) {
48
+ const { label } = this.operator;
49
+ if (this.operator.inputType.type === "date-range") {
50
+ const range = Array.isArray(this.value)
51
+ ? this.value
52
+ : [this.value, this.value];
53
+ return (React__default.createElement(DateRangeEditor, { label: label, value: range, onCommit: (value) => updateActiveFilter({ value }) }));
54
+ }
55
+ const single = Array.isArray(this.value) ? this.value[0] : this.value;
56
+ return (React__default.createElement(DatePicker, { hideLabel: true, label: label, value: single, onChange: (date) => date && updateActiveFilter({ value: date.toString() }) }));
57
+ }
58
+ }
59
+ function DateRangeEditor({ label, onCommit, value: [start, end], }) {
60
+ return (React__default.createElement(Flex, { gap: 1 },
61
+ React__default.createElement(DatePicker, { hideLabel: true, label: `${label} from`, value: start, onChange: (date) => date && onCommit([date.toString(), end]) }),
62
+ React__default.createElement("div", null, "and"),
63
+ React__default.createElement(DatePicker, { hideLabel: true, label: `${label} to`, value: end, onChange: (date) => date && onCommit([start, date.toString()]) })));
64
+ }
65
+
66
+ export { AFTER, BEFORE, DATE_IS, DATE_RANGE, dateFilter };
67
+ //# sourceMappingURL=dateFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dateFilter.js","sources":["../../../src/components/DataTable/dateFilter.tsx"],"sourcesContent":["import { DatePicker } from \"@components/date-picker\"\nimport { Flex } from \"@components/flex\"\nimport {\n DateFormatter,\n getLocalTimeZone,\n parseDate,\n} from \"@internationalized/date\"\nimport React from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n UpdateActiveFilter,\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\nexport const DATE_IS = {\n inputType: { type: \"date\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const BEFORE = {\n inputType: { type: \"date\" },\n label: \"before\",\n name: \"before\",\n} as const satisfies Operator\nexport const AFTER = {\n inputType: { type: \"date\" },\n label: \"after\",\n name: \"after\",\n} as const satisfies Operator\nexport const DATE_RANGE = {\n inputType: { type: \"date-range\" },\n label: \"between\",\n name: \"date_range\",\n} as const satisfies Operator\n\nconst DATE_OPERATORS = [DATE_IS, BEFORE, AFTER, DATE_RANGE]\n\nexport type DateOperatorName = (typeof 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\nexport function dateFilter({\n excludes,\n includes,\n ...config\n}: FilterItemConfig<DateOperatorName>): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new DateActiveFilter(\n filter,\n operator,\n activeFilter.value as DateFilterValue\n ),\n operators: resolveOperators(DATE_OPERATORS, { excludes, includes }),\n }\n return filter\n}\n\nclass DateActiveFilter extends ActiveFilterInstance<DateFilterValue> {\n formatValue() {\n return Array.isArray(this.value)\n ? [formatDate(this.value[0]), \"and\", formatDate(this.value[1])]\n : formatDate(this.value)\n }\n\n renderEditor(updateActiveFilter: UpdateActiveFilter) {\n const { label } = this.operator\n\n if (this.operator.inputType.type === \"date-range\") {\n const range: [string, string] = Array.isArray(this.value)\n ? this.value\n : [this.value, this.value]\n return (\n <DateRangeEditor\n label={label}\n value={range}\n onCommit={(value) => updateActiveFilter({ value })}\n />\n )\n }\n const single = Array.isArray(this.value) ? this.value[0] : this.value\n return (\n <DatePicker\n hideLabel\n label={label}\n value={single}\n onChange={(date) =>\n date && updateActiveFilter({ value: date.toString() })\n }\n />\n )\n }\n}\n\nfunction DateRangeEditor({\n label,\n onCommit,\n value: [start, end],\n}: {\n label: string\n onCommit: (value: [string, string]) => void\n value: [string, string]\n}) {\n return (\n <Flex gap={1}>\n <DatePicker\n hideLabel\n label={`${label} from`}\n value={start}\n onChange={(date) => date && onCommit([date.toString(), end])}\n />\n <div>and</div>\n <DatePicker\n hideLabel\n label={`${label} to`}\n value={end}\n onChange={(date) => date && onCommit([start, date.toString()])}\n />\n </Flex>\n )\n}\n"],"names":["DateFormatter","parseDate","getLocalTimeZone","React"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { collectionFilter } from "./collectionFilter";
2
+ export { dateFilter } from "./dateFilter";
3
+ export { numberFilter } from "./numberFilter";
4
+ export { textFilter } from "./textFilter";
5
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/filters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
@@ -1,5 +1,9 @@
1
1
  import "./index.css";
2
+ import "./filters.css";
2
3
  export type { DataTableElementProps, DataTableLoadingState, DataTableProps, DataTableSelection, } from "./DataTable";
3
4
  export { DataTable } from "./DataTable";
4
5
  export type { BooleanColumn, CurrencyColumn, CustomColumn, DataTableColumn, DataTableColumnAlign, DataTableColumnType, DateColumn, DateTimeColumn, EnumColumn, NumberColumn, StringColumn, } from "./DataTableColumn";
6
+ export * from "./filters";
7
+ export type { ActiveFilter, FilterItemConfig, FilterNode, FilterNodeGroup, FilterNodeItem, Operator, } from "./FilterTypes";
8
+ export type { NumberFilterValue } from "./numberFilter";
5
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AACpB,OAAO,eAAe,CAAA;AAEtB,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,cAAc,EACd,QAAQ,GACT,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,46 @@
1
+ import type { FilterItemConfig, FilterNodeItem } from "./FilterTypes";
2
+ export type NumberFilterValue = number | [number, number];
3
+ export declare const GTE: {
4
+ readonly inputType: {
5
+ readonly type: "number";
6
+ };
7
+ readonly label: ">=";
8
+ readonly name: "gte";
9
+ };
10
+ export declare const LTE: {
11
+ readonly inputType: {
12
+ readonly type: "number";
13
+ };
14
+ readonly label: "<=";
15
+ readonly name: "lte";
16
+ };
17
+ export declare const NUMBER_RANGE: {
18
+ readonly inputType: {
19
+ readonly type: "number-range";
20
+ };
21
+ readonly label: "between";
22
+ readonly name: "number_range";
23
+ };
24
+ declare const NUMBER_OPERATORS: ({
25
+ readonly inputType: {
26
+ readonly type: "number";
27
+ };
28
+ readonly label: ">=";
29
+ readonly name: "gte";
30
+ } | {
31
+ readonly inputType: {
32
+ readonly type: "number";
33
+ };
34
+ readonly label: "<=";
35
+ readonly name: "lte";
36
+ } | {
37
+ readonly inputType: {
38
+ readonly type: "number-range";
39
+ };
40
+ readonly label: "between";
41
+ readonly name: "number_range";
42
+ })[];
43
+ export type NumberOperatorName = (typeof NUMBER_OPERATORS)[number]["name"];
44
+ export declare function numberFilter({ excludes, includes, ...config }: FilterItemConfig<NumberOperatorName>): FilterNodeItem;
45
+ export {};
46
+ //# sourceMappingURL=numberFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numberFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/numberFilter.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EAGf,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,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,YAAY;;;;;;CAII,CAAA;AAE7B,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;IAA2B,CAAA;AAEjD,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1E,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,GAAG,MAAM,EACV,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,GAAG,cAAc,CAYvD"}
@@ -0,0 +1,63 @@
1
+ import { Flex } from '../flex/Flex.js';
2
+ import { NumberStepper } from '../number-stepper/NumberStepper.js';
3
+ import React__default, { useState } from 'react';
4
+ import { ActiveFilterInstance } from './ActiveFilterInstance.js';
5
+ import { resolveOperators } from './resolveOperators.js';
6
+
7
+ const GTE = {
8
+ inputType: { type: "number" },
9
+ label: ">=",
10
+ name: "gte",
11
+ };
12
+ const LTE = {
13
+ inputType: { type: "number" },
14
+ label: "<=",
15
+ name: "lte",
16
+ };
17
+ const NUMBER_RANGE = {
18
+ inputType: { type: "number-range" },
19
+ label: "between",
20
+ name: "number_range",
21
+ };
22
+ const NUMBER_OPERATORS = [GTE, LTE, NUMBER_RANGE];
23
+ function numberFilter({ excludes, includes, ...config }) {
24
+ const filter = {
25
+ ...config,
26
+ createActiveFilterInstance: (activeFilter, operator) => new NumberActiveFilter(filter, operator, activeFilter.value),
27
+ operators: resolveOperators(NUMBER_OPERATORS, { excludes, includes }),
28
+ };
29
+ return filter;
30
+ }
31
+ class NumberActiveFilter extends ActiveFilterInstance {
32
+ formatValue() {
33
+ return Array.isArray(this.value)
34
+ ? this.value.join(" and ")
35
+ : String(this.value);
36
+ }
37
+ renderEditor(updateActiveFilter) {
38
+ const { label } = this.operator;
39
+ const onCommit = (value) => updateActiveFilter({ value });
40
+ if (this.operator.inputType.type === "number-range") {
41
+ const range = Array.isArray(this.value)
42
+ ? this.value
43
+ : [this.value, this.value];
44
+ return (React__default.createElement(NumberRangeEditor, { label: label, value: range, onCommit: onCommit }));
45
+ }
46
+ const single = Array.isArray(this.value) ? this.value[0] : this.value;
47
+ return React__default.createElement(NumberEditor, { label: label, value: single, onCommit: onCommit });
48
+ }
49
+ }
50
+ function NumberEditor({ label, onCommit, value: initialValue, }) {
51
+ const [value, setValue] = useState(initialValue);
52
+ return (React__default.createElement(NumberStepper, { hideLabel: true, label: label, value: value, onChange: setValue, onBlur: () => onCommit(value) }));
53
+ }
54
+ function NumberRangeEditor({ label, onCommit, value: initialValue, }) {
55
+ const [[start, end], setRange] = useState(initialValue);
56
+ return (React__default.createElement(Flex, { gap: 1 },
57
+ React__default.createElement(NumberStepper, { hideLabel: true, label: `${label} from`, value: start, onChange: (value) => setRange([value, end]), onBlur: () => onCommit([start, end]) }),
58
+ React__default.createElement("span", null, "and"),
59
+ React__default.createElement(NumberStepper, { hideLabel: true, label: `${label} to`, value: end, onChange: (value) => setRange([start, value]), onBlur: () => onCommit([start, end]) })));
60
+ }
61
+
62
+ export { GTE, LTE, NUMBER_RANGE, numberFilter };
63
+ //# sourceMappingURL=numberFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numberFilter.js","sources":["../../../src/components/DataTable/numberFilter.tsx"],"sourcesContent":["import { Flex } from \"@components/flex\"\nimport { NumberStepper } from \"@components/number-stepper\"\nimport React, { useState } from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n UpdateActiveFilter,\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 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: \"number_range\",\n} as const satisfies Operator\n\nconst NUMBER_OPERATORS = [GTE, LTE, NUMBER_RANGE]\n\nexport type NumberOperatorName = (typeof NUMBER_OPERATORS)[number][\"name\"]\n\nexport function numberFilter({\n excludes,\n includes,\n ...config\n}: FilterItemConfig<NumberOperatorName>): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new NumberActiveFilter(\n filter,\n operator,\n activeFilter.value as NumberFilterValue\n ),\n operators: resolveOperators(NUMBER_OPERATORS, { excludes, includes }),\n }\n return filter\n}\n\nclass NumberActiveFilter extends ActiveFilterInstance<NumberFilterValue> {\n formatValue() {\n return Array.isArray(this.value)\n ? this.value.join(\" and \")\n : String(this.value)\n }\n\n renderEditor(updateActiveFilter: UpdateActiveFilter) {\n const { label } = this.operator\n const onCommit = (value: NumberFilterValue) => updateActiveFilter({ value })\n\n if (this.operator.inputType.type === \"number-range\") {\n const range: [number, number] = Array.isArray(this.value)\n ? this.value\n : [this.value, this.value]\n return (\n <NumberRangeEditor label={label} value={range} onCommit={onCommit} />\n )\n }\n const single = Array.isArray(this.value) ? this.value[0] : this.value\n return <NumberEditor label={label} value={single} onCommit={onCommit} />\n }\n}\n\nfunction NumberEditor({\n label,\n onCommit,\n value: initialValue,\n}: {\n label: string\n onCommit: (value: number) => void\n value: number\n}) {\n const [value, setValue] = useState(initialValue)\n return (\n <NumberStepper\n hideLabel\n label={label}\n value={value}\n onChange={setValue}\n onBlur={() => onCommit(value)}\n />\n )\n}\n\nfunction NumberRangeEditor({\n label,\n onCommit,\n value: initialValue,\n}: {\n label: string\n onCommit: (value: [number, number]) => void\n value: [number, number]\n}) {\n const [[start, end], setRange] = useState(initialValue)\n return (\n <Flex gap={1}>\n <NumberStepper\n hideLabel\n label={`${label} from`}\n value={start}\n onChange={(value) => setRange([value, end])}\n onBlur={() => onCommit([start, end])}\n />\n <span>and</span>\n <NumberStepper\n hideLabel\n label={`${label} to`}\n value={end}\n onChange={(value) => setRange([start, value])}\n onBlur={() => onCommit([start, end])}\n />\n </Flex>\n )\n}\n"],"names":["React"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Operator } from "./FilterTypes";
2
+ /** `includes` keeps only the named operators, in the order given; `excludes` drops them. */
3
+ export declare function resolveOperators<T extends Operator>(operators: readonly T[], { excludes, includes, }: {
4
+ excludes?: readonly T["name"][];
5
+ includes?: readonly T["name"][];
6
+ }): Operator[];
7
+ //# sourceMappingURL=resolveOperators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveOperators.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/resolveOperators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EACjD,SAAS,EAAE,SAAS,CAAC,EAAE,EACvB,EACE,QAAQ,EACR,QAAQ,GACT,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,CAAA;CAAE,GACtE,QAAQ,EAAE,CAOZ"}
@@ -0,0 +1,11 @@
1
+ /** `includes` keeps only the named operators, in the order given; `excludes` drops them. */
2
+ function resolveOperators(operators, { excludes, includes, }) {
3
+ if (includes)
4
+ return includes.flatMap((name) => operators.find((op) => op.name === name) ?? []);
5
+ if (excludes)
6
+ return operators.filter((op) => !excludes.includes(op.name));
7
+ return [...operators];
8
+ }
9
+
10
+ export { resolveOperators };
11
+ //# sourceMappingURL=resolveOperators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveOperators.js","sources":["../../../src/components/DataTable/resolveOperators.ts"],"sourcesContent":["import type { Operator } from \"./FilterTypes\"\n\n/** `includes` keeps only the named operators, in the order given; `excludes` drops them. */\nexport function resolveOperators<T extends Operator>(\n operators: readonly T[],\n {\n excludes,\n includes,\n }: { excludes?: readonly T[\"name\"][]; includes?: readonly T[\"name\"][] }\n): Operator[] {\n if (includes)\n return includes.flatMap(\n (name) => operators.find((op) => op.name === name) ?? []\n )\n if (excludes) return operators.filter((op) => !excludes.includes(op.name))\n return [...operators]\n}\n"],"names":[],"mappings":"AAEA;AACM,SAAU,gBAAgB,CAC9B,SAAuB,EACvB,EACE,QAAQ,EACR,QAAQ,GAC6D,EAAA;AAEvE,IAAA,IAAI,QAAQ;QACV,OAAO,QAAQ,CAAC,OAAO,CACrB,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CACzD;AACH,IAAA,IAAI,QAAQ;AAAE,QAAA,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AAC1E,IAAA,OAAO,CAAC,GAAG,SAAS,CAAC;AACvB;;;;"}
@@ -0,0 +1,58 @@
1
+ import type { FilterItemConfig, FilterNodeItem } from "./FilterTypes";
2
+ export declare const EQ: {
3
+ readonly inputType: {
4
+ readonly type: "text";
5
+ };
6
+ readonly label: "is";
7
+ readonly name: "eq";
8
+ };
9
+ export declare const CONTAINS: {
10
+ readonly inputType: {
11
+ readonly type: "text";
12
+ };
13
+ readonly label: "contains";
14
+ readonly name: "contains";
15
+ };
16
+ export declare const NOT: {
17
+ readonly inputType: {
18
+ readonly type: "text";
19
+ };
20
+ readonly label: "is not";
21
+ readonly name: "not";
22
+ };
23
+ export declare const STARTS_WITH: {
24
+ readonly inputType: {
25
+ readonly type: "text";
26
+ };
27
+ readonly label: "starts with";
28
+ readonly name: "starts_with";
29
+ };
30
+ declare const TEXT_OPERATORS: ({
31
+ readonly inputType: {
32
+ readonly type: "text";
33
+ };
34
+ readonly label: "is";
35
+ readonly name: "eq";
36
+ } | {
37
+ readonly inputType: {
38
+ readonly type: "text";
39
+ };
40
+ readonly label: "contains";
41
+ readonly name: "contains";
42
+ } | {
43
+ readonly inputType: {
44
+ readonly type: "text";
45
+ };
46
+ readonly label: "is not";
47
+ readonly name: "not";
48
+ } | {
49
+ readonly inputType: {
50
+ readonly type: "text";
51
+ };
52
+ readonly label: "starts with";
53
+ readonly name: "starts_with";
54
+ })[];
55
+ export type TextOperatorName = (typeof TEXT_OPERATORS)[number]["name"];
56
+ export declare function textFilter({ excludes, includes, ...config }: FilterItemConfig<TextOperatorName>): FilterNodeItem;
57
+ export {};
58
+ //# sourceMappingURL=textFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/textFilter.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EAGf,MAAM,eAAe,CAAA;AAGtB,eAAO,MAAM,EAAE;;;;;;CAIc,CAAA;AAC7B,eAAO,MAAM,QAAQ;;;;;;CAIQ,CAAA;AAC7B,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,WAAW;;;;;;CAIK,CAAA;AAE7B,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;IAAmC,CAAA;AAEvD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtE,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,GAAG,MAAM,EACV,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,cAAc,CAQrD"}
@@ -0,0 +1,49 @@
1
+ import { Input } from '../input/Input.js';
2
+ import React__default, { useState } from 'react';
3
+ import { ActiveFilterInstance } from './ActiveFilterInstance.js';
4
+ import { resolveOperators } from './resolveOperators.js';
5
+
6
+ const EQ = {
7
+ inputType: { type: "text" },
8
+ label: "is",
9
+ name: "eq",
10
+ };
11
+ const CONTAINS = {
12
+ inputType: { type: "text" },
13
+ label: "contains",
14
+ name: "contains",
15
+ };
16
+ const NOT = {
17
+ inputType: { type: "text" },
18
+ label: "is not",
19
+ name: "not",
20
+ };
21
+ const STARTS_WITH = {
22
+ inputType: { type: "text" },
23
+ label: "starts with",
24
+ name: "starts_with",
25
+ };
26
+ const TEXT_OPERATORS = [EQ, CONTAINS, NOT, STARTS_WITH];
27
+ function textFilter({ excludes, includes, ...config }) {
28
+ const filter = {
29
+ ...config,
30
+ createActiveFilterInstance: (activeFilter, operator) => new TextActiveFilter(filter, operator, activeFilter.value),
31
+ operators: resolveOperators(TEXT_OPERATORS, { excludes, includes }),
32
+ };
33
+ return filter;
34
+ }
35
+ class TextActiveFilter extends ActiveFilterInstance {
36
+ formatValue() {
37
+ return this.value;
38
+ }
39
+ renderEditor(updateActiveFilter) {
40
+ return (React__default.createElement(TextEditor, { label: this.operator.label, value: this.value, onCommit: (value) => updateActiveFilter({ value }) }));
41
+ }
42
+ }
43
+ function TextEditor({ label, onCommit, value: initialValue, }) {
44
+ const [value, setValue] = useState(initialValue);
45
+ return (React__default.createElement(Input, { hideLabel: true, label: label, value: value, onChange: (e) => setValue(e.target.value), onBlur: () => onCommit(value) }));
46
+ }
47
+
48
+ export { CONTAINS, EQ, NOT, STARTS_WITH, textFilter };
49
+ //# sourceMappingURL=textFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textFilter.js","sources":["../../../src/components/DataTable/textFilter.tsx"],"sourcesContent":["import { Input } from \"@components/input\"\nimport React, { useState } from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n UpdateActiveFilter,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\nexport const EQ = {\n inputType: { type: \"text\" },\n label: \"is\",\n name: \"eq\",\n} as const satisfies Operator\nexport const CONTAINS = {\n inputType: { type: \"text\" },\n label: \"contains\",\n name: \"contains\",\n} as const satisfies Operator\nexport const NOT = {\n inputType: { type: \"text\" },\n label: \"is not\",\n name: \"not\",\n} as const satisfies Operator\nexport const STARTS_WITH = {\n inputType: { type: \"text\" },\n label: \"starts with\",\n name: \"starts_with\",\n} as const satisfies Operator\n\nconst TEXT_OPERATORS = [EQ, CONTAINS, NOT, STARTS_WITH]\n\nexport type TextOperatorName = (typeof TEXT_OPERATORS)[number][\"name\"]\n\nexport function textFilter({\n excludes,\n includes,\n ...config\n}: FilterItemConfig<TextOperatorName>): FilterNodeItem {\n const filter: FilterNodeItem = {\n ...config,\n createActiveFilterInstance: (activeFilter, operator) =>\n new TextActiveFilter(filter, operator, activeFilter.value as string),\n operators: resolveOperators(TEXT_OPERATORS, { excludes, includes }),\n }\n return filter\n}\n\nclass TextActiveFilter extends ActiveFilterInstance<string> {\n formatValue() {\n return this.value\n }\n\n renderEditor(updateActiveFilter: UpdateActiveFilter) {\n return (\n <TextEditor\n label={this.operator.label}\n value={this.value}\n onCommit={(value) => updateActiveFilter({ value })}\n />\n )\n }\n}\n\nfunction TextEditor({\n label,\n onCommit,\n value: initialValue,\n}: {\n label: string\n onCommit: (value: string) => void\n value: string\n}) {\n const [value, setValue] = useState(initialValue)\n return (\n <Input\n hideLabel\n label={label}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onBlur={() => onCommit(value)}\n />\n )\n}\n"],"names":["React"],"mappings":";;;;;AAYO,MAAM,EAAE,GAAG;AAChB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,IAAI;AACX,IAAA,IAAI,EAAE,IAAI;;AAEL,MAAM,QAAQ,GAAG;AACtB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,UAAU;AACjB,IAAA,IAAI,EAAE,UAAU;;AAEX,MAAM,GAAG,GAAG;AACjB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,QAAQ;AACf,IAAA,IAAI,EAAE,KAAK;;AAEN,MAAM,WAAW,GAAG;AACzB,IAAA,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;AAC3B,IAAA,KAAK,EAAE,aAAa;AACpB,IAAA,IAAI,EAAE,aAAa;;AAGrB,MAAM,cAAc,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,CAAC;AAIjD,SAAU,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,GAAG,MAAM,EAC0B,EAAA;AACnC,IAAA,MAAM,MAAM,GAAmB;AAC7B,QAAA,GAAG,MAAM;AACT,QAAA,0BAA0B,EAAE,CAAC,YAAY,EAAE,QAAQ,KACjD,IAAI,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,KAAe,CAAC;QACtE,SAAS,EAAE,gBAAgB,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;KACpE;AACD,IAAA,OAAO,MAAM;AACf;AAEA,MAAM,gBAAiB,SAAQ,oBAA4B,CAAA;IACzD,WAAW,GAAA;QACT,OAAO,IAAI,CAAC,KAAK;IACnB;AAEA,IAAA,YAAY,CAAC,kBAAsC,EAAA;AACjD,QAAA,QACEA,cAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAC1B,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,QAAQ,EAAE,CAAC,KAAK,KAAK,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAA,CAClD;IAEN;AACD;AAED,SAAS,UAAU,CAAC,EAClB,KAAK,EACL,QAAQ,EACR,KAAK,EAAE,YAAY,GAKpB,EAAA;IACC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC;AAChD,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,KAAK,IACJ,SAAS,EAAA,IAAA,EACT,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,MAAM,EAAE,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAA,CAC7B;AAEN;;;;"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Expands the filters shelf when the active filter count leaves zero, and
3
+ * collapses it when the count returns to zero. Returns a toggle to control it.
4
+ */
5
+ export declare function useShelfExpanded(activeFilterCount: number): [boolean, () => void];
6
+ //# sourceMappingURL=useShelfExpanded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useShelfExpanded.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/useShelfExpanded.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,iBAAiB,EAAE,MAAM,GACxB,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAqBvB"}
@@ -0,0 +1,26 @@
1
+ import { useState, useCallback } from 'react';
2
+
3
+ /**
4
+ * Expands the filters shelf when the active filter count leaves zero, and
5
+ * collapses it when the count returns to zero. Returns a toggle to control it.
6
+ */
7
+ function useShelfExpanded(activeFilterCount) {
8
+ const [isShelfExpanded, setIsShelfExpanded] = useState(() => activeFilterCount > 0);
9
+ const [previousCount, setPreviousCount] = useState(activeFilterCount);
10
+ if (activeFilterCount !== previousCount) {
11
+ setPreviousCount(activeFilterCount);
12
+ if (activeFilterCount === 0) {
13
+ setIsShelfExpanded(false);
14
+ }
15
+ else if (previousCount === 0) {
16
+ setIsShelfExpanded(true);
17
+ }
18
+ }
19
+ const toggleShelf = useCallback(() => {
20
+ setIsShelfExpanded((expanded) => !expanded);
21
+ }, []);
22
+ return [isShelfExpanded, toggleShelf];
23
+ }
24
+
25
+ export { useShelfExpanded };
26
+ //# sourceMappingURL=useShelfExpanded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useShelfExpanded.js","sources":["../../../src/components/DataTable/useShelfExpanded.ts"],"sourcesContent":["import { useCallback, useState } from \"react\"\n\n/**\n * Expands the filters shelf when the active filter count leaves zero, and\n * collapses it when the count returns to zero. Returns a toggle to control it.\n */\nexport function useShelfExpanded(\n activeFilterCount: number\n): [boolean, () => void] {\n const [isShelfExpanded, setIsShelfExpanded] = useState(\n () => activeFilterCount > 0\n )\n const [previousCount, setPreviousCount] = useState(activeFilterCount)\n\n if (activeFilterCount !== previousCount) {\n setPreviousCount(activeFilterCount)\n\n if (activeFilterCount === 0) {\n setIsShelfExpanded(false)\n } else if (previousCount === 0) {\n setIsShelfExpanded(true)\n }\n }\n\n const toggleShelf = useCallback(() => {\n setIsShelfExpanded((expanded) => !expanded)\n }, [])\n\n return [isShelfExpanded, toggleShelf]\n}\n"],"names":[],"mappings":";;AAEA;;;AAGG;AACG,SAAU,gBAAgB,CAC9B,iBAAyB,EAAA;AAEzB,IAAA,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CACpD,MAAM,iBAAiB,GAAG,CAAC,CAC5B;IACD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,iBAAiB,CAAC;AAErE,IAAA,IAAI,iBAAiB,KAAK,aAAa,EAAE;QACvC,gBAAgB,CAAC,iBAAiB,CAAC;AAEnC,QAAA,IAAI,iBAAiB,KAAK,CAAC,EAAE;YAC3B,kBAAkB,CAAC,KAAK,CAAC;QAC3B;AAAO,aAAA,IAAI,aAAa,KAAK,CAAC,EAAE;YAC9B,kBAAkB,CAAC,IAAI,CAAC;QAC1B;IACF;AAEA,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;QACnC,kBAAkB,CAAC,CAAC,QAAQ,KAAK,CAAC,QAAQ,CAAC;IAC7C,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,OAAO,CAAC,eAAe,EAAE,WAAW,CAAC;AACvC;;;;"}
@@ -28,6 +28,10 @@ export type DropdownElementProps = DropdownProps;
28
28
  * similar but follow different ARIA patterns (Menu vs Combobox/Listbox) and
29
29
  * are not interchangeable.
30
30
  *
31
+ * **Dropdown vs Popover.** A flat list of actions or links → `Dropdown`.
32
+ * Anything else anchored to a button (a form, a list, plain text) →
33
+ * `Popover`. They're peers, not alternatives for the same content.
34
+ *
31
35
  * Built on React Aria's `MenuTrigger` primitive; popover positioning and menu
32
36
  * identity live on `<DropdownMenu>`.
33
37
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../../src/components/dropdown/Dropdown.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../../src/components/dropdown/Dropdown.tsx"],"names":[],"mappings":"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"}
@@ -19,6 +19,10 @@ import { DropdownTriggerContext } from './DropdownTriggerContext.js';
19
19
  * similar but follow different ARIA patterns (Menu vs Combobox/Listbox) and
20
20
  * are not interchangeable.
21
21
  *
22
+ * **Dropdown vs Popover.** A flat list of actions or links → `Dropdown`.
23
+ * Anything else anchored to a button (a form, a list, plain text) →
24
+ * `Popover`. They're peers, not alternatives for the same content.
25
+ *
22
26
  * Built on React Aria's `MenuTrigger` primitive; popover positioning and menu
23
27
  * identity live on `<DropdownMenu>`.
24
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","sources":["../../../src/components/dropdown/Dropdown.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { Slot } from \"@radix-ui/react-slot\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport classNames from \"classnames\"\nimport React, {\n type ComponentProps,\n type ReactElement,\n type ReactNode,\n useContext,\n useRef,\n} from \"react\"\nimport { FocusScope, useInteractOutside, usePreventScroll } from \"react-aria\"\nimport type {\n Key,\n MenuItemProps,\n MenuSectionProps,\n PopoverProps,\n} from \"react-aria-components\"\nimport {\n Header,\n Menu,\n MenuItem,\n MenuSection,\n MenuTrigger,\n Popover,\n Pressable,\n RootMenuTriggerStateContext,\n Separator,\n} from \"react-aria-components/Menu\"\n\nimport { DropdownTriggerContext } from \"./DropdownTriggerContext\"\n\nexport type DropdownPlacement = NonNullable<PopoverProps[\"placement\"]>\n\nexport interface DropdownProps {\n /**\n * A `<DropdownTrigger>` followed by a `<DropdownMenu>` containing the items.\n */\n children: ReactNode\n /** Fires when the menu closes. */\n onClose?: () => void\n /** Fires when the menu opens. Useful for analytics or lazy data prep. */\n onOpen?: () => void\n}\n\nexport type DropdownElementProps = DropdownProps\n\n/**\n * An action menu — a button that, when activated, reveals a list of actions or\n * navigation links. Composed of a `<DropdownTrigger>` wrapping a Tapestry\n * dropdown-trigger button (`DropdownButton`, `DropdownIconButton`, or\n * `PageHeaderActionsDropdownButton`) and a `<DropdownMenu>` containing\n * `<DropdownAction>`, `<DropdownLink>`, `<DropdownSection>`, and\n * `<DropdownSeparator>` items.\n *\n * **Dropdown vs Select.** Use `Dropdown` to trigger an action (\"Edit\",\n * \"Delete\") or navigate (\"Go to documentation\"). Use `Select` to collect a\n * value that is bound to form data or component state. They look visually\n * similar but follow different ARIA patterns (Menu vs Combobox/Listbox) and\n * are not interchangeable.\n *\n * Built on React Aria's `MenuTrigger` primitive; popover positioning and menu\n * identity live on `<DropdownMenu>`.\n *\n * @component\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/menu/ | W3C APG Menu Pattern}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport function Dropdown({ children, onClose, onOpen }: DropdownElementProps) {\n const handleOpenChange = (isOpen: boolean) => {\n if (isOpen) onOpen?.()\n else onClose?.()\n }\n\n return <MenuTrigger onOpenChange={handleOpenChange}>{children}</MenuTrigger>\n}\n\nexport interface DropdownMenuProps {\n /**\n * `<DropdownAction>` / `<DropdownLink>` / `<DropdownSection>` /\n * `<DropdownSeparator>` elements.\n */\n children: ReactNode\n /** Override for the underlying `<Menu>` element id. */\n id?: string\n /**\n * Popover position relative to the trigger. Uses React Aria's\n * space-separated format (e.g., `\"bottom start\"`, `\"top end\"`,\n * `\"left top\"`). Defaults to `\"bottom start\"`.\n */\n placement?: DropdownPlacement\n}\n\nexport type DropdownMenuElementProps = DropdownMenuProps\n\n/**\n * The popover surface for a `<Dropdown>`. Wraps React Aria's `<Popover>` and\n * `<Menu>` and contains the menu items.\n *\n * @component\n */\nexport function DropdownMenu({\n children,\n id,\n placement = \"bottom start\",\n}: DropdownMenuElementProps) {\n const popoverRef = useRef<HTMLElement>(null)\n const state = useContext(RootMenuTriggerStateContext)\n\n useInteractOutside({\n isDisabled: !state?.isOpen,\n onInteractOutside: () => state?.close(),\n ref: popoverRef,\n })\n usePreventScroll({ isDisabled: !state?.isOpen })\n\n return (\n <Popover\n className=\"tds-dropdown-popover\"\n isNonModal\n placement={placement}\n ref={popoverRef}\n shouldCloseOnInteractOutside={() => false}\n >\n <FocusScope contain>\n <Menu id={id}>{children}</Menu>\n </FocusScope>\n </Popover>\n )\n}\n\nexport interface DropdownTriggerProps {\n /**\n * A single Tapestry dropdown-trigger button element (`DropdownButton`,\n * `DropdownIconButton`, or `PageHeaderActionsDropdownButton`).\n */\n children: ReactElement\n /**\n * Whether the trigger is disabled. This is the single source of truth for the\n * trigger's disabled state — a `disabled` set directly on the child button\n * does not win.\n */\n disabled?: boolean\n}\n\n/**\n * Wraps a single Tapestry dropdown-trigger button and bridges it to React\n * Aria's `MenuTrigger` via `<Pressable>`.\n * Uses context to pass `disabled` to the trigger button.\n *\n * @component\n */\ntype PressableChild = ComponentProps<typeof Pressable>[\"children\"]\n\nexport function DropdownTrigger({ children, disabled }: DropdownTriggerProps) {\n return (\n <DropdownTriggerContext.Provider value={{ disabled }}>\n <Pressable isDisabled={disabled}>{children as PressableChild}</Pressable>\n </DropdownTriggerContext.Provider>\n )\n}\n\nexport interface DropdownItemBaseProps {\n /** Applies destructive styling. */\n destructive?: boolean\n /** Applies staff-only visual treatment. */\n staffOnly?: boolean\n}\n\nexport interface DropdownActionProps extends DropdownItemBaseProps {\n /**\n * Disables the item. Renamed to React Aria's `isDisabled` inside the\n * wrapper. Disabled items are skipped by keyboard traversal and won't fire\n * `onAction`.\n */\n disabled?: boolean\n /**\n * Stable identifier — required by React Aria's collection model for keying\n * and focus tracking.\n */\n id: Key\n /**\n * Callback fired when the item is activated.\n *\n * React Aria closes the menu and returns focus to the trigger after this\n * runs, which can override a focus change made here — e.g. focusing a\n * nearby input. If `onAction` needs to move focus elsewhere, wrap that\n * part in `queueMicrotask` to defer it until after React Aria's\n * focus-restore has finished: `queueMicrotask(() => inputRef.current?.focus())`.\n */\n onAction: () => void\n}\n\ntype AriaActionPropsToOmit =\n | \"href\"\n | \"isDisabled\"\n | \"rel\"\n | \"routerOptions\"\n | \"target\"\n | \"value\"\ntype AriaActionPropsToInclude = \"textValue\"\n\nexport type DropdownActionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n MenuItemProps<T>,\n DropdownActionProps,\n AriaActionPropsToOmit,\n AriaActionPropsToInclude\n >\n\n/**\n * A `<Dropdown>` item that fires a callback when activated. Renders an RA\n * `<MenuItem>` (`role=\"menuitem\"`). Children are passed through and can use\n * the slot convention (`slot=\"label\" | \"prefix\" | \"suffix\" | \"description\"`)\n * for structured content.\n *\n * @component\n */\nexport function DropdownAction<T extends object>({\n className,\n destructive,\n disabled,\n staffOnly,\n ...restProps\n}: DropdownActionElementProps<T>) {\n return (\n <MenuItem\n {...restProps}\n className={classNames(\n \"tds-dropdown-item\",\n {\n \"tds-dropdown-item--destructive\": destructive,\n \"tds-dropdown-item--staff-only\": staffOnly,\n },\n className\n )}\n isDisabled={disabled}\n />\n )\n}\n\nexport interface DropdownLinkBaseProps extends DropdownItemBaseProps {\n /** If `true`, sets `target=\"_blank\"` and `rel=\"noreferrer noopener\"`. */\n external?: boolean\n /**\n * Stable identifier — required by React Aria's collection model for keying\n * and focus tracking.\n */\n id: Key\n}\n\nexport interface DropdownLinkAsChildProps extends DropdownLinkBaseProps {\n /**\n * Merge menu item behavior onto a single child element (e.g. a router\n * `Link`) instead of rendering an `<a>`. When true, `href` must not be set.\n * **Not supported in Rails.**\n */\n asChild: true\n href?: never\n}\n\nexport interface DropdownLinkHrefProps extends DropdownLinkBaseProps {\n asChild?: false\n /** Destination URL. */\n href: string\n}\n\nexport type DropdownLinkProps = DropdownLinkAsChildProps | DropdownLinkHrefProps\n\ntype AriaLinkPropsToOmit =\n | \"isDisabled\"\n | \"onAction\"\n | \"rel\"\n | \"render\"\n | \"target\"\n | \"value\"\ntype AriaLinkPropsToInclude = \"routerOptions\" | \"textValue\"\n\nexport type DropdownLinkElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n MenuItemProps<T>,\n DropdownLinkProps,\n AriaLinkPropsToOmit,\n AriaLinkPropsToInclude\n >\n\n/** Strips RAC-injected `undefined` values (e.g. `href`) that would otherwise clobber a child's own prop of the same name via `Slot`. */\nfunction omitUndefinedValues<T extends object>(props: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined)\n ) as Partial<T>\n}\n\n/**\n * A `<Dropdown>` item that navigates to a URL. Renders an RA `<MenuItem>` as\n * an anchor (`<a role=\"menuitem\" href=\"…\">`). Pass `external` to open in a\n * new tab with `rel=\"noreferrer noopener\"`.\n *\n * `disabled` is intentionally not accepted — HTML has no native disabled state\n * for anchors, and a \"disabled link\" has no accessible analog. If a link\n * shouldn't be activatable, omit it.\n *\n * @component\n */\nexport function DropdownLink<T extends object>({\n asChild = false,\n children,\n className,\n destructive,\n external,\n staffOnly,\n ...restProps\n}: DropdownLinkElementProps<T>) {\n const externalProps = external\n ? { rel: \"noreferrer noopener\", target: \"_blank\" as const }\n : null\n return (\n <MenuItem\n {...restProps}\n {...externalProps}\n className={classNames(\n \"tds-dropdown-item\",\n {\n \"tds-dropdown-item--destructive\": destructive,\n \"tds-dropdown-item--staff-only\": staffOnly,\n },\n className\n )}\n render={\n asChild\n ? (props) => (\n <Slot {...omitUndefinedValues(props)}>\n {children as ReactElement}\n </Slot>\n )\n : undefined\n }\n >\n {asChild ? undefined : children}\n </MenuItem>\n )\n}\n\nexport interface DropdownSectionProps {\n /** The items rendered within the section. */\n children: ReactNode\n /**\n * Heading rendered above the section's items. Required — RA renders the\n * section as `role=\"group\"` and the heading provides the group's\n * accessible name via `aria-labelledby`.\n */\n title: string\n}\n\nexport type DropdownSectionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n MenuSectionProps<T>,\n DropdownSectionProps,\n \"value\",\n never\n >\n\n/**\n * A grouped section within a `<Dropdown>`. Renders an RA `<MenuSection>`\n * (`role=\"group\"`) with an optional `<Header>` heading when `title` is set.\n *\n * @component\n */\nexport function DropdownSection<T extends object>({\n children,\n className,\n title,\n ...restProps\n}: DropdownSectionElementProps<T>) {\n return (\n <MenuSection\n {...restProps}\n className={classNames(\"tds-dropdown-section\", className)}\n >\n <Header className=\"tds-dropdown-section-label\">{title}</Header>\n {children}\n </MenuSection>\n )\n}\n\nexport type DropdownSeparatorElementProps = Record<string, never>\n\n/**\n * A divider between items in a `<Dropdown>`. Renders an RA `<Separator>`\n * (`role=\"separator\"`).\n *\n * @component\n */\nexport function DropdownSeparator() {\n return <Separator className=\"tds-dropdown-separator\" />\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.js","sources":["../../../src/components/dropdown/Dropdown.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { Slot } from \"@radix-ui/react-slot\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport classNames from \"classnames\"\nimport React, {\n type ComponentProps,\n type ReactElement,\n type ReactNode,\n useContext,\n useRef,\n} from \"react\"\nimport { FocusScope, useInteractOutside, usePreventScroll } from \"react-aria\"\nimport type {\n Key,\n MenuItemProps,\n MenuSectionProps,\n PopoverProps,\n} from \"react-aria-components\"\nimport {\n Header,\n Menu,\n MenuItem,\n MenuSection,\n MenuTrigger,\n Popover,\n Pressable,\n RootMenuTriggerStateContext,\n Separator,\n} from \"react-aria-components/Menu\"\n\nimport { DropdownTriggerContext } from \"./DropdownTriggerContext\"\n\nexport type DropdownPlacement = NonNullable<PopoverProps[\"placement\"]>\n\nexport interface DropdownProps {\n /**\n * A `<DropdownTrigger>` followed by a `<DropdownMenu>` containing the items.\n */\n children: ReactNode\n /** Fires when the menu closes. */\n onClose?: () => void\n /** Fires when the menu opens. Useful for analytics or lazy data prep. */\n onOpen?: () => void\n}\n\nexport type DropdownElementProps = DropdownProps\n\n/**\n * An action menu — a button that, when activated, reveals a list of actions or\n * navigation links. Composed of a `<DropdownTrigger>` wrapping a Tapestry\n * dropdown-trigger button (`DropdownButton`, `DropdownIconButton`, or\n * `PageHeaderActionsDropdownButton`) and a `<DropdownMenu>` containing\n * `<DropdownAction>`, `<DropdownLink>`, `<DropdownSection>`, and\n * `<DropdownSeparator>` items.\n *\n * **Dropdown vs Select.** Use `Dropdown` to trigger an action (\"Edit\",\n * \"Delete\") or navigate (\"Go to documentation\"). Use `Select` to collect a\n * value that is bound to form data or component state. They look visually\n * similar but follow different ARIA patterns (Menu vs Combobox/Listbox) and\n * are not interchangeable.\n *\n * **Dropdown vs Popover.** A flat list of actions or links → `Dropdown`.\n * Anything else anchored to a button (a form, a list, plain text) →\n * `Popover`. They're peers, not alternatives for the same content.\n *\n * Built on React Aria's `MenuTrigger` primitive; popover positioning and menu\n * identity live on `<DropdownMenu>`.\n *\n * @component\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/menu/ | W3C APG Menu Pattern}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport function Dropdown({ children, onClose, onOpen }: DropdownElementProps) {\n const handleOpenChange = (isOpen: boolean) => {\n if (isOpen) onOpen?.()\n else onClose?.()\n }\n\n return <MenuTrigger onOpenChange={handleOpenChange}>{children}</MenuTrigger>\n}\n\nexport interface DropdownMenuProps {\n /**\n * `<DropdownAction>` / `<DropdownLink>` / `<DropdownSection>` /\n * `<DropdownSeparator>` elements.\n */\n children: ReactNode\n /** Override for the underlying `<Menu>` element id. */\n id?: string\n /**\n * Popover position relative to the trigger. Uses React Aria's\n * space-separated format (e.g., `\"bottom start\"`, `\"top end\"`,\n * `\"left top\"`). Defaults to `\"bottom start\"`.\n */\n placement?: DropdownPlacement\n}\n\nexport type DropdownMenuElementProps = DropdownMenuProps\n\n/**\n * The popover surface for a `<Dropdown>`. Wraps React Aria's `<Popover>` and\n * `<Menu>` and contains the menu items.\n *\n * @component\n */\nexport function DropdownMenu({\n children,\n id,\n placement = \"bottom start\",\n}: DropdownMenuElementProps) {\n const popoverRef = useRef<HTMLElement>(null)\n const state = useContext(RootMenuTriggerStateContext)\n\n useInteractOutside({\n isDisabled: !state?.isOpen,\n onInteractOutside: () => state?.close(),\n ref: popoverRef,\n })\n usePreventScroll({ isDisabled: !state?.isOpen })\n\n return (\n <Popover\n className=\"tds-dropdown-popover\"\n isNonModal\n placement={placement}\n ref={popoverRef}\n shouldCloseOnInteractOutside={() => false}\n >\n <FocusScope contain>\n <Menu id={id}>{children}</Menu>\n </FocusScope>\n </Popover>\n )\n}\n\nexport interface DropdownTriggerProps {\n /**\n * A single Tapestry dropdown-trigger button element (`DropdownButton`,\n * `DropdownIconButton`, or `PageHeaderActionsDropdownButton`).\n */\n children: ReactElement\n /**\n * Whether the trigger is disabled. This is the single source of truth for the\n * trigger's disabled state — a `disabled` set directly on the child button\n * does not win.\n */\n disabled?: boolean\n}\n\n/**\n * Wraps a single Tapestry dropdown-trigger button and bridges it to React\n * Aria's `MenuTrigger` via `<Pressable>`.\n * Uses context to pass `disabled` to the trigger button.\n *\n * @component\n */\ntype PressableChild = ComponentProps<typeof Pressable>[\"children\"]\n\nexport function DropdownTrigger({ children, disabled }: DropdownTriggerProps) {\n return (\n <DropdownTriggerContext.Provider value={{ disabled }}>\n <Pressable isDisabled={disabled}>{children as PressableChild}</Pressable>\n </DropdownTriggerContext.Provider>\n )\n}\n\nexport interface DropdownItemBaseProps {\n /** Applies destructive styling. */\n destructive?: boolean\n /** Applies staff-only visual treatment. */\n staffOnly?: boolean\n}\n\nexport interface DropdownActionProps extends DropdownItemBaseProps {\n /**\n * Disables the item. Renamed to React Aria's `isDisabled` inside the\n * wrapper. Disabled items are skipped by keyboard traversal and won't fire\n * `onAction`.\n */\n disabled?: boolean\n /**\n * Stable identifier — required by React Aria's collection model for keying\n * and focus tracking.\n */\n id: Key\n /**\n * Callback fired when the item is activated.\n *\n * React Aria closes the menu and returns focus to the trigger after this\n * runs, which can override a focus change made here — e.g. focusing a\n * nearby input. If `onAction` needs to move focus elsewhere, wrap that\n * part in `queueMicrotask` to defer it until after React Aria's\n * focus-restore has finished: `queueMicrotask(() => inputRef.current?.focus())`.\n */\n onAction: () => void\n}\n\ntype AriaActionPropsToOmit =\n | \"href\"\n | \"isDisabled\"\n | \"rel\"\n | \"routerOptions\"\n | \"target\"\n | \"value\"\ntype AriaActionPropsToInclude = \"textValue\"\n\nexport type DropdownActionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n MenuItemProps<T>,\n DropdownActionProps,\n AriaActionPropsToOmit,\n AriaActionPropsToInclude\n >\n\n/**\n * A `<Dropdown>` item that fires a callback when activated. Renders an RA\n * `<MenuItem>` (`role=\"menuitem\"`). Children are passed through and can use\n * the slot convention (`slot=\"label\" | \"prefix\" | \"suffix\" | \"description\"`)\n * for structured content.\n *\n * @component\n */\nexport function DropdownAction<T extends object>({\n className,\n destructive,\n disabled,\n staffOnly,\n ...restProps\n}: DropdownActionElementProps<T>) {\n return (\n <MenuItem\n {...restProps}\n className={classNames(\n \"tds-dropdown-item\",\n {\n \"tds-dropdown-item--destructive\": destructive,\n \"tds-dropdown-item--staff-only\": staffOnly,\n },\n className\n )}\n isDisabled={disabled}\n />\n )\n}\n\nexport interface DropdownLinkBaseProps extends DropdownItemBaseProps {\n /** If `true`, sets `target=\"_blank\"` and `rel=\"noreferrer noopener\"`. */\n external?: boolean\n /**\n * Stable identifier — required by React Aria's collection model for keying\n * and focus tracking.\n */\n id: Key\n}\n\nexport interface DropdownLinkAsChildProps extends DropdownLinkBaseProps {\n /**\n * Merge menu item behavior onto a single child element (e.g. a router\n * `Link`) instead of rendering an `<a>`. When true, `href` must not be set.\n * **Not supported in Rails.**\n */\n asChild: true\n href?: never\n}\n\nexport interface DropdownLinkHrefProps extends DropdownLinkBaseProps {\n asChild?: false\n /** Destination URL. */\n href: string\n}\n\nexport type DropdownLinkProps = DropdownLinkAsChildProps | DropdownLinkHrefProps\n\ntype AriaLinkPropsToOmit =\n | \"isDisabled\"\n | \"onAction\"\n | \"rel\"\n | \"render\"\n | \"target\"\n | \"value\"\ntype AriaLinkPropsToInclude = \"routerOptions\" | \"textValue\"\n\nexport type DropdownLinkElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n MenuItemProps<T>,\n DropdownLinkProps,\n AriaLinkPropsToOmit,\n AriaLinkPropsToInclude\n >\n\n/** Strips RAC-injected `undefined` values (e.g. `href`) that would otherwise clobber a child's own prop of the same name via `Slot`. */\nfunction omitUndefinedValues<T extends object>(props: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined)\n ) as Partial<T>\n}\n\n/**\n * A `<Dropdown>` item that navigates to a URL. Renders an RA `<MenuItem>` as\n * an anchor (`<a role=\"menuitem\" href=\"…\">`). Pass `external` to open in a\n * new tab with `rel=\"noreferrer noopener\"`.\n *\n * `disabled` is intentionally not accepted — HTML has no native disabled state\n * for anchors, and a \"disabled link\" has no accessible analog. If a link\n * shouldn't be activatable, omit it.\n *\n * @component\n */\nexport function DropdownLink<T extends object>({\n asChild = false,\n children,\n className,\n destructive,\n external,\n staffOnly,\n ...restProps\n}: DropdownLinkElementProps<T>) {\n const externalProps = external\n ? { rel: \"noreferrer noopener\", target: \"_blank\" as const }\n : null\n return (\n <MenuItem\n {...restProps}\n {...externalProps}\n className={classNames(\n \"tds-dropdown-item\",\n {\n \"tds-dropdown-item--destructive\": destructive,\n \"tds-dropdown-item--staff-only\": staffOnly,\n },\n className\n )}\n render={\n asChild\n ? (props) => (\n <Slot {...omitUndefinedValues(props)}>\n {children as ReactElement}\n </Slot>\n )\n : undefined\n }\n >\n {asChild ? undefined : children}\n </MenuItem>\n )\n}\n\nexport interface DropdownSectionProps {\n /** The items rendered within the section. */\n children: ReactNode\n /**\n * Heading rendered above the section's items. Required — RA renders the\n * section as `role=\"group\"` and the heading provides the group's\n * accessible name via `aria-labelledby`.\n */\n title: string\n}\n\nexport type DropdownSectionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n MenuSectionProps<T>,\n DropdownSectionProps,\n \"value\",\n never\n >\n\n/**\n * A grouped section within a `<Dropdown>`. Renders an RA `<MenuSection>`\n * (`role=\"group\"`) with an optional `<Header>` heading when `title` is set.\n *\n * @component\n */\nexport function DropdownSection<T extends object>({\n children,\n className,\n title,\n ...restProps\n}: DropdownSectionElementProps<T>) {\n return (\n <MenuSection\n {...restProps}\n className={classNames(\"tds-dropdown-section\", className)}\n >\n <Header className=\"tds-dropdown-section-label\">{title}</Header>\n {children}\n </MenuSection>\n )\n}\n\nexport type DropdownSeparatorElementProps = Record<string, never>\n\n/**\n * A divider between items in a `<Dropdown>`. Renders an RA `<Separator>`\n * (`role=\"separator\"`).\n *\n * @component\n */\nexport function DropdownSeparator() {\n return <Separator className=\"tds-dropdown-separator\" />\n}\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import "./index.css";
2
2
  import React, { type InputHTMLAttributes } from "react";
3
3
  export type InputSize = "lg" | "md";
4
- export type InputType = "email" | "number" | "password" | "search" | "tel" | "text" | "url";
4
+ export type InputType = "email" | "file" | "number" | "password" | "search" | "tel" | "text" | "url";
5
5
  interface InputBaseProps {
6
6
  /** Helper text displayed below the input. Styled as an error when `invalid`. */
7
7
  description?: React.ReactNode;
@@ -50,9 +50,9 @@ export type InputProps = InputWithAriaLabelledBy | InputWithHiddenLabel | InputW
50
50
  export type InputElementProps = Omit<InputHTMLAttributes<HTMLInputElement>, keyof InputProps | keyof InputSizingProps | "size" | "type"> & InputProps & InputSizingProps;
51
51
  /**
52
52
  * A text input component that renders as an HTML `<input>` with a label and
53
- * optional description. Supports the standard text-like input types
54
- * (`text`, `email`, `password`, `search`, `tel`, `url`, `number`), invalid
55
- * state, and `lg`/`md` sizing.
53
+ * optional description. Supports the standard native input types
54
+ * (`text`, `email`, `password`, `search`, `tel`, `url`, `number`, `file`),
55
+ * invalid state, and `lg`/`md` sizing.
56
56
  *
57
57
  * @component
58
58
  * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-input--docs | Storybook Documentation}
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,KAAK,CAAA;AAET,UAAU,cAAc;IACtB,gFAAgF;IAChF,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,kBAAkB;IAC1B,uFAAuF;IACvF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,KAAK,CAAA;CACf;AAED,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,6HAA6H;IAC7H,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,KAAK,gBAAgB,GAAG,kBAAkB,GAAG,eAAe,CAAA;AAE5D,UAAU,qBAAsB,SAAQ,cAAc;IACpD,mEAAmE;IACnE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,oBAAqB,SAAQ,cAAc;IACnD,mEAAmE;IACnE,SAAS,EAAE,IAAI,CAAA;IACf,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAClB,uBAAuB,GACvB,oBAAoB,GACpB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAC5D,GACC,UAAU,GACV,gBAAgB,CAAA;AAElB;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,4FA6EjB,CAAA"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,MAAM,GACN,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,KAAK,CAAA;AAET,UAAU,cAAc;IACtB,gFAAgF;IAChF,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,kBAAkB;IAC1B,uFAAuF;IACvF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,KAAK,CAAA;CACf;AAED,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,6HAA6H;IAC7H,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,KAAK,gBAAgB,GAAG,kBAAkB,GAAG,eAAe,CAAA;AAE5D,UAAU,qBAAsB,SAAQ,cAAc;IACpD,mEAAmE;IACnE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,oBAAqB,SAAQ,cAAc;IACnD,mEAAmE;IACnE,SAAS,EAAE,IAAI,CAAA;IACf,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAClB,uBAAuB,GACvB,oBAAoB,GACpB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAC5D,GACC,UAAU,GACV,gBAAgB,CAAA;AAElB;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,4FA6EjB,CAAA"}
@@ -4,9 +4,9 @@ import React__default, { forwardRef } from 'react';
4
4
 
5
5
  /**
6
6
  * A text input component that renders as an HTML `<input>` with a label and
7
- * optional description. Supports the standard text-like input types
8
- * (`text`, `email`, `password`, `search`, `tel`, `url`, `number`), invalid
9
- * state, and `lg`/`md` sizing.
7
+ * optional description. Supports the standard native input types
8
+ * (`text`, `email`, `password`, `search`, `tel`, `url`, `number`, `file`),
9
+ * invalid state, and `lg`/`md` sizing.
10
10
  *
11
11
  * @component
12
12
  * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-input--docs | Storybook Documentation}