@planningcenter/tapestry 4.12.0-rc.0 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DataTable/CollectionEditorsLazy.js +2 -1
- package/dist/components/DataTable/CollectionEditorsLazy.js.map +1 -1
- package/dist/components/DataTable/DataTable.d.ts +5 -4
- package/dist/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.js +4 -2
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/ManageSavedViewsModal.d.ts +5 -2
- package/dist/components/DataTable/ManageSavedViewsModal.d.ts.map +1 -1
- package/dist/components/DataTable/ManageSavedViewsModal.js +167 -18
- package/dist/components/DataTable/ManageSavedViewsModal.js.map +1 -1
- package/dist/components/DataTable/ManageSavedViewsModal.module.css.js +1 -1
- package/dist/components/DataTable/SavedViewsBar.d.ts.map +1 -1
- package/dist/components/DataTable/SavedViewsBar.js +23 -9
- package/dist/components/DataTable/SavedViewsBar.js.map +1 -1
- package/dist/components/DataTable/savedViews.d.ts +24 -0
- package/dist/components/DataTable/savedViews.d.ts.map +1 -1
- package/dist/components/DataTable/savedViews.js +58 -1
- package/dist/components/DataTable/savedViews.js.map +1 -1
- package/dist/components/button/ActionsDropdownIconButton.d.ts +3 -2
- package/dist/components/button/ActionsDropdownIconButton.d.ts.map +1 -1
- package/dist/components/button/ActionsDropdownIconButton.js.map +1 -1
- package/dist/components/button/BaseButton.d.ts.map +1 -1
- package/dist/components/button/BaseButton.js +2 -1
- package/dist/components/button/BaseButton.js.map +1 -1
- package/dist/components/button/IconButton.d.ts +1 -3
- package/dist/components/button/IconButton.d.ts.map +1 -1
- package/dist/components/button/IconButton.js.map +1 -1
- package/dist/components/button/ToggleIconButton.d.ts +5 -2
- package/dist/components/button/ToggleIconButton.d.ts.map +1 -1
- package/dist/components/button/ToggleIconButton.js +1 -0
- package/dist/components/button/ToggleIconButton.js.map +1 -1
- package/dist/components/button/index.d.ts +1 -1
- package/dist/components/button/index.d.ts.map +1 -1
- package/dist/components/combo-box/ComboBox.d.ts +2 -0
- package/dist/components/combo-box/ComboBox.d.ts.map +1 -1
- package/dist/components/combo-box/ComboBox.js +31 -5
- package/dist/components/combo-box/ComboBox.js.map +1 -1
- package/dist/components/date-picker/DatePicker.d.ts.map +1 -1
- package/dist/components/date-picker/DatePicker.js +18 -14
- package/dist/components/date-picker/DatePicker.js.map +1 -1
- package/dist/components/internal/LoadingAnnouncement.d.ts +11 -0
- package/dist/components/internal/LoadingAnnouncement.d.ts.map +1 -0
- package/dist/components/internal/LoadingAnnouncement.js +21 -0
- package/dist/components/internal/LoadingAnnouncement.js.map +1 -0
- package/dist/components/internal/index.d.ts +1 -0
- package/dist/components/internal/index.d.ts.map +1 -1
- package/dist/components/internal/tooltip/Tooltip.d.ts +4 -2
- package/dist/components/internal/tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/internal/tooltip/Tooltip.js.map +1 -1
- package/dist/components/internal/tooltip/TooltipTriggerContext.d.ts +3 -3
- package/dist/components/internal/tooltip/TooltipTriggerContext.d.ts.map +1 -1
- package/dist/components/internal/tooltip/TooltipTriggerContext.js +1 -1
- package/dist/components/internal/tooltip/TooltipTriggerContext.js.map +1 -1
- package/dist/components/internal/tooltip/index.d.ts +1 -1
- package/dist/components/internal/tooltip/index.d.ts.map +1 -1
- package/dist/components/link/BaseLink.d.ts.map +1 -1
- package/dist/components/link/BaseLink.js +15 -3
- package/dist/components/link/BaseLink.js.map +1 -1
- package/dist/components/link/IconLink.d.ts +28 -290
- package/dist/components/link/IconLink.d.ts.map +1 -1
- package/dist/components/link/IconLink.js +9 -2
- package/dist/components/link/IconLink.js.map +1 -1
- package/dist/components/page-header/defineElements.js +1 -1
- package/dist/components/pane/Pane.d.ts +1 -1
- package/dist/components/pane/Pane.js +1 -1
- package/dist/components/pane/Pane.js.map +1 -1
- package/dist/components/pane/PaneBody.d.ts +1 -1
- package/dist/components/pane/PaneBody.js +1 -1
- package/dist/components/pane/PaneBody.js.map +1 -1
- package/dist/components/pane/PaneDivider.d.ts +1 -1
- package/dist/components/pane/PaneDivider.js +1 -1
- package/dist/components/pane/PaneDivider.js.map +1 -1
- package/dist/components/pane/PaneFooter.d.ts +1 -1
- package/dist/components/pane/PaneFooter.js +1 -1
- package/dist/components/pane/PaneFooter.js.map +1 -1
- package/dist/components/pane/PaneHeader.d.ts +1 -1
- package/dist/components/pane/PaneHeader.js +1 -1
- package/dist/components/pane/PaneHeader.js.map +1 -1
- package/dist/components/pane/PaneHeaderActions.d.ts +1 -1
- package/dist/components/pane/PaneHeaderActions.js +1 -1
- package/dist/components/pane/PaneHeaderActions.js.map +1 -1
- package/dist/components/sidenav/defineElements.js +1 -1
- package/dist/components/time-field/TimeField.d.ts.map +1 -1
- package/dist/components/time-field/TimeField.js +7 -3
- package/dist/components/time-field/TimeField.js.map +1 -1
- package/dist/index.css +142 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/packages/tapestry-wc/dist/components/{p-np7vhMVg.js → p-A1JK45WV.js} +3 -3
- package/dist/packages/tapestry-wc/dist/components/p-A1JK45WV.js.map +1 -0
- package/dist/packages/tapestry-wc/dist/components/{p-BVvtAaVT.js → p-BbuNAv9q.js} +3 -3
- package/dist/packages/tapestry-wc/dist/components/p-BbuNAv9q.js.map +1 -0
- package/dist/packages/tapestry-wc/dist/components/{p-B2xqMgNQ.js → p-CBFtMIxJ.js} +2 -2
- package/dist/packages/tapestry-wc/dist/components/p-CBFtMIxJ.js.map +1 -0
- package/dist/packages/tapestry-wc/dist/components/{p-Rn6lOB18.js → p-CY_DC4d_.js} +3 -3
- package/dist/packages/tapestry-wc/dist/components/p-CY_DC4d_.js.map +1 -0
- package/dist/packages/tapestry-wc/dist/components/{p-6NO22Vi_.js → p-DNHgMtxw.js} +2 -2
- package/dist/packages/tapestry-wc/dist/components/p-DNHgMtxw.js.map +1 -0
- package/dist/packages/tapestry-wc/dist/components/tds-page-header-nav.js +2 -2
- package/dist/packages/tapestry-wc/dist/components/tds-page-header-nav.js.map +1 -1
- package/dist/packages/tapestry-wc/dist/components/tds-page-header.js +3 -3
- package/dist/packages/tapestry-wc/dist/components/tds-page-header.js.map +1 -1
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav-item.js +3 -3
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav-item.js.map +1 -1
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav-responsive-header.js +2 -2
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav-responsive-header.js.map +1 -1
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav-section.js +3 -3
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav-section.js.map +1 -1
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav.js +5 -5
- package/dist/packages/tapestry-wc/dist/components/tds-sidenav.js.map +1 -1
- package/dist/reactRender.css +1171 -1101
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +1171 -1101
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/tapestryMount.css +1171 -1101
- package/dist/tapestryMount.css.map +1 -1
- package/dist/tapestryMountLegacy.css +1171 -1101
- package/dist/tapestryMountLegacy.css.map +1 -1
- package/dist/unstable.css +201 -131
- package/dist/unstable.css.map +1 -1
- package/dist/unstable.d.ts +0 -1
- package/dist/unstable.d.ts.map +1 -1
- package/dist/unstable.js +6 -6
- package/dist/utilities/dateFieldLocale.d.ts +2 -0
- package/dist/utilities/dateFieldLocale.d.ts.map +1 -0
- package/dist/utilities/dateFieldLocale.js +32 -0
- package/dist/utilities/dateFieldLocale.js.map +1 -0
- package/dist/utilities/useAnnounce.d.ts +8 -1
- package/dist/utilities/useAnnounce.d.ts.map +1 -1
- package/dist/utilities/useAnnounce.js.map +1 -1
- package/dist/utilities/useDateFieldLocale.d.ts +2 -0
- package/dist/utilities/useDateFieldLocale.d.ts.map +1 -0
- package/dist/utilities/useDateFieldLocale.js +11 -0
- package/dist/utilities/useDateFieldLocale.js.map +1 -0
- package/package.json +4 -3
- package/dist/packages/tapestry-wc/dist/components/p-6NO22Vi_.js.map +0 -1
- package/dist/packages/tapestry-wc/dist/components/p-B2xqMgNQ.js.map +0 -1
- package/dist/packages/tapestry-wc/dist/components/p-BVvtAaVT.js.map +0 -1
- package/dist/packages/tapestry-wc/dist/components/p-Rn6lOB18.js.map +0 -1
- package/dist/packages/tapestry-wc/dist/components/p-np7vhMVg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"savedViews.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/savedViews.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"savedViews.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/savedViews.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,IAAI,CAAC,EAAE,IAAI,CAAA;IACX;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,uCAAuC;AACvC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAA;AAE5D;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,UAIzB,CAAA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAOnE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAOxE;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,SAAS,EAAE,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,OAAO,GAAG,QAAQ,GAC/B,SAAS,EAAE,CAmBb;AAED,UAAU,cAAc;IACtB,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,IAAI,EAAE,IAAI,GAAG,SAAS,CAAA;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,SAAS,EAAE,EACvB,KAAK,EAAE,cAAc,GACpB,SAAS,GAAG,SAAS,CAYvB"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { generateNKeysBetween, generateKeyBetween } from 'fractional-indexing';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Always listed, so there's a view to fall back to. Added before the static
|
|
3
5
|
* views unless one of them uses its id, which replaces it.
|
|
@@ -7,6 +9,61 @@ const initialView = {
|
|
|
7
9
|
id: "initial",
|
|
8
10
|
name: "All",
|
|
9
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Views by `sortKey`, then views without one, each in array order. Compares
|
|
14
|
+
* by code unit rather than locale, since keys mix upper and lower case.
|
|
15
|
+
*/
|
|
16
|
+
function sortSavedViews(savedViews) {
|
|
17
|
+
return [...savedViews].sort((a, b) => {
|
|
18
|
+
if (a.sortKey === b.sortKey)
|
|
19
|
+
return 0;
|
|
20
|
+
if (a.sortKey === undefined)
|
|
21
|
+
return 1;
|
|
22
|
+
if (b.sortKey === undefined)
|
|
23
|
+
return -1;
|
|
24
|
+
return a.sortKey < b.sortKey ? -1 : 1;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A `sortKey` after every view's, for a view added at the end. Undefined
|
|
29
|
+
* while any view has no key, since those are listed last, so a view added
|
|
30
|
+
* without one stays at the end.
|
|
31
|
+
*/
|
|
32
|
+
function sortKeyAfter(savedViews) {
|
|
33
|
+
let lastSortKey = null;
|
|
34
|
+
for (const { sortKey } of savedViews) {
|
|
35
|
+
if (sortKey === undefined)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (lastSortKey === null || sortKey > lastSortKey)
|
|
38
|
+
lastSortKey = sortKey;
|
|
39
|
+
}
|
|
40
|
+
return generateKeyBetween(lastSortKey, null);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The views to update so the view at `from` is dropped before or after the
|
|
44
|
+
* view at `target`, both positions in the order. Usually just the dropped
|
|
45
|
+
* view, with a key between its new neighbors'. Dropping among views without
|
|
46
|
+
* a key also gives a key to those before it, since they come after every
|
|
47
|
+
* view with one.
|
|
48
|
+
*/
|
|
49
|
+
function savedViewUpdatesForReorder(savedViews, from, target, dropPosition) {
|
|
50
|
+
let to = dropPosition === "after" ? target + 1 : target;
|
|
51
|
+
// Taking the view out shifts the views after it up one.
|
|
52
|
+
if (from < to)
|
|
53
|
+
to--;
|
|
54
|
+
if (from === to)
|
|
55
|
+
return [];
|
|
56
|
+
const newOrder = [...savedViews];
|
|
57
|
+
const [view] = newOrder.splice(from, 1);
|
|
58
|
+
newOrder.splice(to, 0, view);
|
|
59
|
+
let start = to;
|
|
60
|
+
while (start > 0 && newOrder[start - 1].sortKey === undefined)
|
|
61
|
+
start--;
|
|
62
|
+
const keys = generateNKeysBetween(newOrder[start - 1]?.sortKey ?? null, newOrder[to + 1]?.sortKey ?? null, to - start + 1);
|
|
63
|
+
return newOrder
|
|
64
|
+
.slice(start, to + 1)
|
|
65
|
+
.map((view, index) => ({ ...view, sortKey: keys[index] }));
|
|
66
|
+
}
|
|
10
67
|
/**
|
|
11
68
|
* The most specific view matching the current state, or undefined. Only
|
|
12
69
|
* picks the initially selected view. Filters match regardless of order,
|
|
@@ -69,5 +126,5 @@ function namesMatch(a, b) {
|
|
|
69
126
|
return new Set(a).size === names.size && a.every((name) => names.has(name));
|
|
70
127
|
}
|
|
71
128
|
|
|
72
|
-
export { findActiveSavedView, initialView };
|
|
129
|
+
export { findActiveSavedView, initialView, savedViewUpdatesForReorder, sortKeyAfter, sortSavedViews };
|
|
73
130
|
//# sourceMappingURL=savedViews.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"savedViews.js","sources":["../../../src/components/DataTable/savedViews.ts"],"sourcesContent":["import type { Sort } from \"./DataTable\"\nimport type { ActiveFilter } from \"./FilterTypes\"\n\nexport interface SavedView {\n activeFilters: ActiveFilter[]\n /** Omit to leave the current column visibility unchanged when applied. */\n hiddenColumnNames?: string[]\n /** Assigned by the consumer once the view is saved. */\n id?: number | string\n name: string\n /** Omit to leave the current sort unchanged when applied. */\n sort?: Sort\n}\n\n/** An app-provided view. Read-only. */\nexport type StaticView = SavedView & { id: number | string }\n\n/**\n * Always listed, so there's a view to fall back to. Added before the static\n * views unless one of them uses its id, which replaces it.\n */\nexport const initialView: StaticView = {\n activeFilters: [],\n id: \"initial\",\n name: \"All\",\n}\n\ninterface SavedViewState {\n activeFilters: ActiveFilter[]\n hiddenColumnNames: string[]\n sort: Sort | undefined\n}\n\n/**\n * The most specific view matching the current state, or undefined. Only\n * picks the initially selected view. Filters match regardless of order,\n * ignoring display-only labels. A view's `sort` and `hiddenColumnNames` are\n * only compared when the view sets them, so a view that sets more of them is\n * more specific. Among equally specific matches, the first wins.\n */\nexport function findActiveSavedView(\n savedViews: SavedView[],\n state: SavedViewState\n): SavedView | undefined {\n let mostSpecificMatch: SavedView | undefined\n for (const view of savedViews) {\n if (!savedViewMatches(view, state)) continue\n if (\n !mostSpecificMatch ||\n specificity(view) > specificity(mostSpecificMatch)\n ) {\n mostSpecificMatch = view\n }\n }\n return mostSpecificMatch\n}\n\nfunction specificity(view: SavedView): number {\n return Number(Boolean(view.sort)) + Number(Boolean(view.hiddenColumnNames))\n}\n\nfunction savedViewMatches(view: SavedView, state: SavedViewState): boolean {\n if (!filtersMatch(view.activeFilters, state.activeFilters)) return false\n if (view.sort && !sortMatches(view.sort, state.sort)) return false\n return (\n !view.hiddenColumnNames ||\n namesMatch(view.hiddenColumnNames, state.hiddenColumnNames)\n )\n}\n\nfunction filtersMatch(a: ActiveFilter[], b: ActiveFilter[]): boolean {\n if (a.length !== b.length) return false\n const unmatched = [...b]\n return a.every((filter) => {\n const index = unmatched.findIndex((other) => filterMatches(filter, other))\n if (index === -1) return false\n unmatched.splice(index, 1)\n return true\n })\n}\n\nfunction filterMatches(a: ActiveFilter, b: ActiveFilter): boolean {\n return (\n a.name === b.name &&\n a.operator === b.operator &&\n a.scope === b.scope &&\n valueMatches(a.value, b.value)\n )\n}\n\nfunction valueMatches(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((item, i) => item === b[i])\n }\n return a === b\n}\n\nfunction sortMatches(a: Sort, b: Sort | undefined): boolean {\n return a.column === b?.column && a.direction === b?.direction\n}\n\nfunction namesMatch(a: string[], b: string[]): boolean {\n const names = new Set(b)\n return new Set(a).size === names.size && a.every((name) => names.has(name))\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"savedViews.js","sources":["../../../src/components/DataTable/savedViews.ts"],"sourcesContent":["import { generateKeyBetween, generateNKeysBetween } from \"fractional-indexing\"\n\nimport type { Sort } from \"./DataTable\"\nimport type { ActiveFilter } from \"./FilterTypes\"\n\nexport interface SavedView {\n activeFilters: ActiveFilter[]\n /** Omit to leave the current column visibility unchanged when applied. */\n hiddenColumnNames?: string[]\n /** Assigned by the consumer once the view is saved. */\n id?: number | string\n name: string\n /** Omit to leave the current sort unchanged when applied. */\n sort?: Sort\n /**\n * The view's position, as a fractional index. Views without one are listed\n * after those with one.\n */\n sortKey?: string\n}\n\n/** An app-provided view. Read-only. */\nexport type StaticView = SavedView & { id: number | string }\n\n/**\n * Always listed, so there's a view to fall back to. Added before the static\n * views unless one of them uses its id, which replaces it.\n */\nexport const initialView: StaticView = {\n activeFilters: [],\n id: \"initial\",\n name: \"All\",\n}\n\n/**\n * Views by `sortKey`, then views without one, each in array order. Compares\n * by code unit rather than locale, since keys mix upper and lower case.\n */\nexport function sortSavedViews(savedViews: SavedView[]): SavedView[] {\n return [...savedViews].sort((a, b) => {\n if (a.sortKey === b.sortKey) return 0\n if (a.sortKey === undefined) return 1\n if (b.sortKey === undefined) return -1\n return a.sortKey < b.sortKey ? -1 : 1\n })\n}\n\n/**\n * A `sortKey` after every view's, for a view added at the end. Undefined\n * while any view has no key, since those are listed last, so a view added\n * without one stays at the end.\n */\nexport function sortKeyAfter(savedViews: SavedView[]): string | undefined {\n let lastSortKey: string | null = null\n for (const { sortKey } of savedViews) {\n if (sortKey === undefined) return undefined\n if (lastSortKey === null || sortKey > lastSortKey) lastSortKey = sortKey\n }\n return generateKeyBetween(lastSortKey, null)\n}\n\n/**\n * The views to update so the view at `from` is dropped before or after the\n * view at `target`, both positions in the order. Usually just the dropped\n * view, with a key between its new neighbors'. Dropping among views without\n * a key also gives a key to those before it, since they come after every\n * view with one.\n */\nexport function savedViewUpdatesForReorder(\n savedViews: SavedView[],\n from: number,\n target: number,\n dropPosition: \"after\" | \"before\"\n): SavedView[] {\n let to = dropPosition === \"after\" ? target + 1 : target\n // Taking the view out shifts the views after it up one.\n if (from < to) to--\n if (from === to) return []\n const newOrder = [...savedViews]\n const [view] = newOrder.splice(from, 1)\n newOrder.splice(to, 0, view)\n\n let start = to\n while (start > 0 && newOrder[start - 1].sortKey === undefined) start--\n const keys = generateNKeysBetween(\n newOrder[start - 1]?.sortKey ?? null,\n newOrder[to + 1]?.sortKey ?? null,\n to - start + 1\n )\n return newOrder\n .slice(start, to + 1)\n .map((view, index) => ({ ...view, sortKey: keys[index] }))\n}\n\ninterface SavedViewState {\n activeFilters: ActiveFilter[]\n hiddenColumnNames: string[]\n sort: Sort | undefined\n}\n\n/**\n * The most specific view matching the current state, or undefined. Only\n * picks the initially selected view. Filters match regardless of order,\n * ignoring display-only labels. A view's `sort` and `hiddenColumnNames` are\n * only compared when the view sets them, so a view that sets more of them is\n * more specific. Among equally specific matches, the first wins.\n */\nexport function findActiveSavedView(\n savedViews: SavedView[],\n state: SavedViewState\n): SavedView | undefined {\n let mostSpecificMatch: SavedView | undefined\n for (const view of savedViews) {\n if (!savedViewMatches(view, state)) continue\n if (\n !mostSpecificMatch ||\n specificity(view) > specificity(mostSpecificMatch)\n ) {\n mostSpecificMatch = view\n }\n }\n return mostSpecificMatch\n}\n\nfunction specificity(view: SavedView): number {\n return Number(Boolean(view.sort)) + Number(Boolean(view.hiddenColumnNames))\n}\n\nfunction savedViewMatches(view: SavedView, state: SavedViewState): boolean {\n if (!filtersMatch(view.activeFilters, state.activeFilters)) return false\n if (view.sort && !sortMatches(view.sort, state.sort)) return false\n return (\n !view.hiddenColumnNames ||\n namesMatch(view.hiddenColumnNames, state.hiddenColumnNames)\n )\n}\n\nfunction filtersMatch(a: ActiveFilter[], b: ActiveFilter[]): boolean {\n if (a.length !== b.length) return false\n const unmatched = [...b]\n return a.every((filter) => {\n const index = unmatched.findIndex((other) => filterMatches(filter, other))\n if (index === -1) return false\n unmatched.splice(index, 1)\n return true\n })\n}\n\nfunction filterMatches(a: ActiveFilter, b: ActiveFilter): boolean {\n return (\n a.name === b.name &&\n a.operator === b.operator &&\n a.scope === b.scope &&\n valueMatches(a.value, b.value)\n )\n}\n\nfunction valueMatches(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((item, i) => item === b[i])\n }\n return a === b\n}\n\nfunction sortMatches(a: Sort, b: Sort | undefined): boolean {\n return a.column === b?.column && a.direction === b?.direction\n}\n\nfunction namesMatch(a: string[], b: string[]): boolean {\n const names = new Set(b)\n return new Set(a).size === names.size && a.every((name) => names.has(name))\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type TooltipPlacement } from "../internal/tooltip";
|
|
1
2
|
import { ComponentSize } from "../../utilities/buttonLinkShared";
|
|
2
3
|
import React from "react";
|
|
3
|
-
import { IconButtonBaseProps
|
|
4
|
+
import { IconButtonBaseProps } from "./IconButton";
|
|
4
5
|
export type ActionsDropdownIconButtonProps = Omit<IconButtonBaseProps, "aria-label" | "icon" | "kind" | "loading" | "size"> & {
|
|
5
6
|
/**
|
|
6
7
|
* Accessible name. Defaults to `"Actions"` when `tooltip` is not set.
|
|
@@ -49,7 +50,7 @@ export type ActionsDropdownIconButtonProps = Omit<IconButtonBaseProps, "aria-lab
|
|
|
49
50
|
*
|
|
50
51
|
* @component
|
|
51
52
|
*/
|
|
52
|
-
export declare const ActionsDropdownIconButton: React.ForwardRefExoticComponent<Omit<IconButtonBaseProps, "
|
|
53
|
+
export declare const ActionsDropdownIconButton: React.ForwardRefExoticComponent<Omit<IconButtonBaseProps, "size" | "icon" | "aria-label" | "kind" | "loading"> & {
|
|
53
54
|
/**
|
|
54
55
|
* Accessible name. Defaults to `"Actions"` when `tooltip` is not set.
|
|
55
56
|
* Override when a page has several actions menus that need
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionsDropdownIconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/ActionsDropdownIconButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,OAAO,KAAiC,MAAM,OAAO,CAAA;AAErD,OAAO,EAAc,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"ActionsDropdownIconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/ActionsDropdownIconButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,OAAO,KAAiC,MAAM,OAAO,CAAA;AAErD,OAAO,EAAc,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAE9D,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAC/C,mBAAmB,EACnB,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CACpD,GAAG;IACF;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,CAAA;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;IACnC,qEAAqE;IACrE,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,wSAAwS;IACxS,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;IAhDpC;;;;OAIG;mBACY,MAAM;IACrB;;;OAGG;gBACS,KAAK;IACjB,yEAAyE;WAClE,KAAK;IACZ;;;OAGG;WACI,OAAO,GAAG,SAAS;IAC1B;;;OAGG;cACO,KAAK;IACf;;;OAGG;aACM,KAAK;IACd;;;;OAIG;WACI,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC;IACnC,qEAAqE;aAC5D,KAAK;IACd,wSAAwS;cAC9R,MAAM;IAChB,6GAA6G;uBAC1F,gBAAgB;2CAiDpC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionsDropdownIconButton.js","sources":["../../../src/components/button/ActionsDropdownIconButton.tsx"],"sourcesContent":["import { DropdownTriggerContext } from \"@components/dropdown/DropdownTriggerContext\"\nimport { ComponentSize } from \"@utilities/buttonLinkShared\"\nimport Icon from \"@utilities/Icon\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, useContext } from \"react\"\n\nimport { IconButton, IconButtonBaseProps
|
|
1
|
+
{"version":3,"file":"ActionsDropdownIconButton.js","sources":["../../../src/components/button/ActionsDropdownIconButton.tsx"],"sourcesContent":["import { DropdownTriggerContext } from \"@components/dropdown/DropdownTriggerContext\"\nimport { type TooltipPlacement } from \"@components/internal/tooltip\"\nimport { ComponentSize } from \"@utilities/buttonLinkShared\"\nimport Icon from \"@utilities/Icon\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, useContext } from \"react\"\n\nimport { IconButton, IconButtonBaseProps } from \"./IconButton\"\n\nexport type ActionsDropdownIconButtonProps = Omit<\n IconButtonBaseProps,\n \"aria-label\" | \"icon\" | \"kind\" | \"loading\" | \"size\"\n> & {\n /**\n * Accessible name. Defaults to `\"Actions\"` when `tooltip` is not set.\n * Override when a page has several actions menus that need\n * distinguishing (e.g. `\"Actions for Jane Doe\"`).\n */\n \"aria-label\"?: string\n /**\n * Not supported — an actions trigger is a fixed-size icon button and\n * shouldn't stretch to fill a container. Always rendered as `false`.\n */\n fullWidth?: never\n /** Not supported — the vertical ellipsis is the component's identity. */\n icon?: never\n /**\n * Only `\"ghost\"` and `\"neutral\"` are supported treatments for an actions\n * trigger. Defaults to `\"ghost\"`.\n */\n kind?: \"ghost\" | \"neutral\"\n /**\n * Not supported — `.tds-btn--loading` hides every non-spinner child, so a\n * loading actions button would render a bare spinner with no glyph.\n */\n loading?: never\n /**\n * Not supported — same reasoning as `suffix`: total control over the\n * button's contents, and no slot besides the fixed ellipsis icon.\n */\n prefix?: never\n /**\n * `xs` is excluded — at 20px effective height it falls below the WCAG 2.2\n * AA 24×24 minimum target size, and an icon-only button has no text\n * content to widen it past the minimum.\n */\n size?: Exclude<ComponentSize, \"xs\">\n /** Not supported — no caret, and nothing else in the suffix slot. */\n suffix?: never\n /** Text shown on hover and focus. Without `aria-label`, it is also used as the `aria-label`. With `aria-label`, start the `aria-label` with the same text (e.g. tooltip `\"Delete\"`, aria-label `\"Delete, 3 selected\"`). The tooltip itself is hidden from screen readers. Ignores `aria-labelledby`. */\n tooltip?: string\n /** Where the tooltip renders relative to the button. Default `\"bottom\"`. Has no effect without `tooltip`. */\n tooltipPlacement?: TooltipPlacement\n}\n\n/**\n * An icon-only dropdown trigger with a vertical-ellipsis glyph and no\n * caret, for action menus where a caret is visually redundant.\n *\n * @component\n */\nexport const ActionsDropdownIconButton = forwardRef<\n HTMLButtonElement,\n ActionsDropdownIconButtonProps\n>(\n (\n {\n \"aria-label\": ariaLabel,\n className,\n kind = \"ghost\",\n tooltip,\n ...restProps\n }: ActionsDropdownIconButtonProps,\n ref\n ) => {\n const contextProps = useContext(DropdownTriggerContext)\n const nameProps = tooltip\n ? { \"aria-label\": ariaLabel, tooltip }\n : { \"aria-label\": ariaLabel ?? \"Actions\" }\n return (\n <IconButton\n ref={ref}\n {...restProps}\n {...contextProps}\n {...nameProps}\n className={classNames(className, \"tds-btn--actions-dropdown\")}\n fullWidth={false}\n icon={\n <Icon\n className=\"actions-icon\"\n symbol=\"general#three-dots\"\n aria-hidden\n />\n }\n kind={kind}\n loading={undefined}\n prefix={undefined}\n suffix={undefined}\n />\n )\n }\n)\n\nActionsDropdownIconButton.displayName = \"ActionsDropdownIconButton\"\n"],"names":[],"mappings":";;;;;;AAuDA;;;;;AAKG;AACI,MAAM,yBAAyB,GAAG,UAAU,CAIjD,CACE,EACE,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,IAAI,GAAG,OAAO,EACd,OAAO,EACP,GAAG,SAAS,EACmB,EACjC,GAAG,KACD;AACF,IAAA,MAAM,YAAY,GAAG,UAAU,CAAC,sBAAsB,CAAC;IACvD,MAAM,SAAS,GAAG;AAChB,UAAE,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO;UAClC,EAAE,YAAY,EAAE,SAAS,IAAI,SAAS,EAAE;IAC5C,QACE,KAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,GAAG,EAAE,GAAG,EAAA,GACJ,SAAS,EAAA,GACT,YAAY,EAAA,GACZ,SAAS,EACb,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,2BAA2B,CAAC,EAC7D,SAAS,EAAE,KAAK,EAChB,IAAI,EACF,oBAAC,IAAI,EAAA,EACH,SAAS,EAAC,cAAc,EACxB,MAAM,EAAC,oBAAoB,EAAA,aAAA,EAAA,IAAA,EAAA,CAE3B,EAEJ,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,SAAS,EAAA,CACjB;AAEN,CAAC;AAGH,yBAAyB,CAAC,WAAW,GAAG,2BAA2B;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/BaseButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAIlB,OAAO,EACL,kBAAkB,EAGlB,aAAa,EAEd,MAAM,6BAA6B,CAAA;AAEpC,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"BaseButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/BaseButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAIlB,OAAO,EACL,kBAAkB,EAGlB,aAAa,EAEd,MAAM,6BAA6B,CAAA;AAEpC,OAAO,KAAK,EAAE,EACZ,oBAAoB,EAIrB,MAAM,OAAO,CAAA;AAId,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACvE,sCAAsC;IACtC,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB,sCAAsC;IACtC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,+GAA+G;IAC/G,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,eAAe,GAAG,UAAU,CACnC,GACC,eAAe,CAAA;AAEjB,eAAO,MAAM,UAAU,qLAkEtB,CAAA"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import LoadingSpinner from '../internal/LoadingSpinner.js';
|
|
2
|
+
import React, { forwardRef, useContext } from 'react';
|
|
3
|
+
import 'react-aria/private/live-announcer/LiveAnnouncer';
|
|
2
4
|
import '../internal/tooltip/Tooltip.js';
|
|
3
5
|
import { TooltipTriggerContext } from '../internal/tooltip/TooltipTriggerContext.js';
|
|
4
6
|
import { COMPONENT_SIZE_CLASS_MAP, COMPONENT_KIND_CLASS_MAP, wrapStringWithSpan } from '../../utilities/buttonLinkShared.js';
|
|
5
7
|
import classNames from 'classnames';
|
|
6
|
-
import React, { forwardRef, useContext } from 'react';
|
|
7
8
|
import { mergeProps } from 'react-aria/mergeProps';
|
|
8
9
|
import { mergeRefs } from 'react-aria/mergeRefs';
|
|
9
10
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseButton.js","sources":["../../../src/components/button/BaseButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport { LoadingSpinner } from \"@components/internal\"\nimport { TooltipTriggerContext } from \"@components/internal/tooltip/TooltipTriggerContext\"\nimport {\n BaseComponentProps,\n COMPONENT_KIND_CLASS_MAP,\n COMPONENT_SIZE_CLASS_MAP,\n ComponentKind,\n wrapStringWithSpan,\n} from \"@utilities/buttonLinkShared\"\nimport classNames from \"classnames\"\nimport React, {
|
|
1
|
+
{"version":3,"file":"BaseButton.js","sources":["../../../src/components/button/BaseButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport { LoadingSpinner } from \"@components/internal\"\nimport { TooltipTriggerContext } from \"@components/internal/tooltip/TooltipTriggerContext\"\nimport {\n BaseComponentProps,\n COMPONENT_KIND_CLASS_MAP,\n COMPONENT_SIZE_CLASS_MAP,\n ComponentKind,\n wrapStringWithSpan,\n} from \"@utilities/buttonLinkShared\"\nimport classNames from \"classnames\"\nimport React, {\n ButtonHTMLAttributes,\n forwardRef,\n RefObject,\n useContext,\n} from \"react\"\nimport { mergeProps } from \"react-aria/mergeProps\"\nimport { mergeRefs } from \"react-aria/mergeRefs\"\n\nexport interface BaseButtonProps extends Omit<BaseComponentProps, \"kind\"> {\n /** The visual style of the button. */\n kind?: ComponentKind\n /** The text content of the button. */\n label: React.ReactNode\n /** Whether the button is in a loading state. When true, the button is disabled and shows a loading spinner. */\n loading?: boolean\n /** Accessible label to use when the button is in loading state. */\n loadingAriaLabel?: string\n}\n\nexport type BaseButtonElementProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof BaseButtonProps | \"children\"\n> &\n BaseButtonProps\n\nexport const BaseButton = forwardRef<HTMLButtonElement, BaseButtonElementProps>(\n (\n {\n \"aria-describedby\": ariaDescribedBy,\n \"aria-label\": ariaLabel,\n className,\n disabled = false,\n fullWidth,\n kind = \"secondary\",\n label,\n loading = false,\n loadingAriaLabel = \"Loading...\",\n prefix,\n size,\n suffix,\n ...restProps\n }: BaseButtonElementProps,\n ref\n ) => {\n const tooltip = useContext(TooltipTriggerContext)\n const { \"aria-describedby\": tooltipId, ...tooltipTriggerProps } =\n tooltip?.triggerProps ?? {}\n\n const mergedProps = tooltip\n ? mergeProps(restProps, tooltipTriggerProps)\n : restProps\n const mergedRef = tooltip\n ? mergeRefs<HTMLButtonElement>(\n ref,\n tooltip.ref as RefObject<HTMLButtonElement>\n )\n : ref\n const describedBy =\n [ariaDescribedBy, tooltipId].filter(Boolean).join(\" \") || undefined\n\n const combinedClassName = classNames(\n kind && \"tds-btn\",\n size && size !== \"md\" && COMPONENT_SIZE_CLASS_MAP[size],\n kind && COMPONENT_KIND_CLASS_MAP[kind],\n fullWidth && \"tds-btn--full-width\",\n loading && \"tds-btn--loading\",\n className,\n { \"tds-btn--prefix\": prefix, \"tds-btn--suffix\": suffix }\n )\n\n const isDisabled = disabled || loading\n\n return (\n <button\n type=\"button\"\n className={combinedClassName}\n ref={mergedRef}\n {...mergedProps}\n aria-busy={loading || undefined}\n aria-describedby={describedBy}\n aria-disabled={isDisabled || undefined}\n disabled={isDisabled}\n aria-label={loading ? loadingAriaLabel : ariaLabel}\n >\n {loading && <LoadingSpinner />}\n {wrapStringWithSpan(prefix)}\n {loading ? <span>{label}</span> : label}\n {wrapStringWithSpan(suffix)}\n </button>\n )\n }\n)\n\nBaseButton.displayName = \"BaseButton\"\n"],"names":[],"mappings":";;;;;;;;;;MAsCa,UAAU,GAAG,UAAU,CAClC,CACE,EACE,kBAAkB,EAAE,eAAe,EACnC,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,QAAQ,GAAG,KAAK,EAChB,SAAS,EACT,IAAI,GAAG,WAAW,EAClB,KAAK,EACL,OAAO,GAAG,KAAK,EACf,gBAAgB,GAAG,YAAY,EAC/B,MAAM,EACN,IAAI,EACJ,MAAM,EACN,GAAG,SAAS,EACW,EACzB,GAAG,KACD;AACF,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,qBAAqB,CAAC;AACjD,IAAA,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,GAAG,mBAAmB,EAAE,GAC7D,OAAO,EAAE,YAAY,IAAI,EAAE;IAE7B,MAAM,WAAW,GAAG;AAClB,UAAE,UAAU,CAAC,SAAS,EAAE,mBAAmB;UACzC,SAAS;IACb,MAAM,SAAS,GAAG;UACd,SAAS,CACP,GAAG,EACH,OAAO,CAAC,GAAmC;UAE7C,GAAG;AACP,IAAA,MAAM,WAAW,GACf,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS;IAErE,MAAM,iBAAiB,GAAG,UAAU,CAClC,IAAI,IAAI,SAAS,EACjB,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC,EACvD,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC,EACtC,SAAS,IAAI,qBAAqB,EAClC,OAAO,IAAI,kBAAkB,EAC7B,SAAS,EACT,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,CACzD;AAED,IAAA,MAAM,UAAU,GAAG,QAAQ,IAAI,OAAO;AAEtC,IAAA,QACE,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,iBAAiB,EAC5B,GAAG,EAAE,SAAS,KACV,WAAW,EAAA,WAAA,EACJ,OAAO,IAAI,SAAS,EAAA,kBAAA,EACb,WAAW,mBACd,UAAU,IAAI,SAAS,EACtC,QAAQ,EAAE,UAAU,EAAA,YAAA,EACR,OAAO,GAAG,gBAAgB,GAAG,SAAS,EAAA;QAEjD,OAAO,IAAI,KAAA,CAAA,aAAA,CAAC,cAAc,EAAA,IAAA,CAAG;QAC7B,kBAAkB,CAAC,MAAM,CAAC;QAC1B,OAAO,GAAG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,EAAO,KAAK,CAAQ,GAAG,KAAK;AACtC,QAAA,kBAAkB,CAAC,MAAM,CAAC,CACpB;AAEb,CAAC;AAGH,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import "./btn.css";
|
|
2
|
+
import { type TooltipPlacement } from "../internal/tooltip";
|
|
2
3
|
import React from "react";
|
|
3
|
-
import { type Placement } from "react-aria/useOverlayPosition";
|
|
4
4
|
import { BaseButtonElementProps } from "./BaseButton";
|
|
5
|
-
/** Where a tooltip renders relative to its button. */
|
|
6
|
-
export type TooltipPlacement = Placement;
|
|
7
5
|
type IconButtonSharedProps = Omit<BaseButtonElementProps, "label"> & {
|
|
8
6
|
/** The icon to display in the button. Set via story args for non-primitive values. */
|
|
9
7
|
icon: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/IconButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/IconButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAElB,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE7E,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAc,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAEjE,KAAK,qBAAqB,GAAG,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,GAAG;IACnE,sFAAsF;IACtF,IAAI,EAAE,KAAK,CAAC,SAAS,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,GAAG;IACxD,sGAAsG;IACtG,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC5B,8MAA8M;IAC9M,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wSAAwS;IACxS,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,8MAA8M;IAC9M,YAAY,EAAE,MAAM,CAAA;IACpB,wSAAwS;IACxS,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,KAAK,mBAAmB,GAAG,wBAAwB,GAAG,sBAAsB,CAAA;AAE5E,MAAM,MAAM,eAAe,GAAG,qBAAqB,GACjD,mBAAmB,GAAG;IACpB,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC,CAAA;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,2FA0CtB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IconButton.js","sources":["../../../src/components/button/IconButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport { Tooltip } from \"@components/internal/tooltip\"\nimport classNames from \"classnames\"\nimport React, { forwardRef } from \"react\"\
|
|
1
|
+
{"version":3,"file":"IconButton.js","sources":["../../../src/components/button/IconButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport { Tooltip, type TooltipPlacement } from \"@components/internal/tooltip\"\nimport classNames from \"classnames\"\nimport React, { forwardRef } from \"react\"\n\nimport { BaseButton, BaseButtonElementProps } from \"./BaseButton\"\n\ntype IconButtonSharedProps = Omit<BaseButtonElementProps, \"label\"> & {\n /** The icon to display in the button. Set via story args for non-primitive values. */\n icon: React.ReactNode\n}\n\nexport type IconButtonBaseProps = IconButtonSharedProps & {\n /** Accessible label. Required for icon-only buttons to provide context about the button's purpose. */\n \"aria-label\": string\n}\n\ntype IconButtonTooltipProps = {\n /** Accessible label. Required for icon-only buttons to provide context about the button's purpose. Not required when `tooltip` is set. When both are set, this is the name and the tooltip is visual only. */\n \"aria-label\"?: string\n /** Text shown on hover and focus. Without `aria-label`, it is also used as the `aria-label`. With `aria-label`, start the `aria-label` with the same text (e.g. tooltip `\"Delete\"`, aria-label `\"Delete, 3 selected\"`). The tooltip itself is hidden from screen readers. Ignores `aria-labelledby`. */\n tooltip: string\n}\n\ntype IconButtonAriaLabelProps = {\n /** Accessible label. Required for icon-only buttons to provide context about the button's purpose. Not required when `tooltip` is set. When both are set, this is the name and the tooltip is visual only. */\n \"aria-label\": string\n /** Text shown on hover and focus. Without `aria-label`, it is also used as the `aria-label`. With `aria-label`, start the `aria-label` with the same text (e.g. tooltip `\"Delete\"`, aria-label `\"Delete, 3 selected\"`). The tooltip itself is hidden from screen readers. Ignores `aria-labelledby`. */\n tooltip?: string\n}\n\n/**\n * An icon-only button needs a name: `aria-label`, `tooltip`, or both.\n * `IconButtonAriaLabelProps` is declared last so that a missing name\n * reports \"aria-label is missing\", not \"tooltip is missing\".\n */\ntype IconButtonNameProps = IconButtonAriaLabelProps | IconButtonTooltipProps\n\nexport type IconButtonProps = IconButtonSharedProps &\n IconButtonNameProps & {\n /** Where the tooltip renders relative to the button. Default `\"bottom\"`. Has no effect without `tooltip`. */\n tooltipPlacement?: TooltipPlacement\n }\n\n/**\n * An icon-only button component that renders as a button element.\n * Requires an icon, and an aria-label or tooltip for accessibility.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/buttons-icon-button--docs | Storybook Documentation}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n {\n className,\n icon,\n tooltip,\n tooltipPlacement = \"bottom\",\n ...restProps\n }: IconButtonProps,\n ref\n ) => {\n const iconOnlyClassName = classNames(\"tds-btn--icononly\", className)\n\n if (tooltip) {\n const {\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n ...buttonProps\n } = restProps\n\n return (\n <Tooltip content={tooltip} placement={tooltipPlacement} visualOnly>\n <BaseButton\n {...buttonProps}\n aria-label={ariaLabel || tooltip}\n label={icon}\n className={iconOnlyClassName}\n ref={ref}\n />\n </Tooltip>\n )\n }\n\n return (\n <BaseButton\n {...restProps}\n label={icon}\n className={iconOnlyClassName}\n ref={ref}\n />\n )\n }\n)\n\nIconButton.displayName = \"IconButton\"\n"],"names":[],"mappings":";;;;;AA6CA;;;;;;;AAOG;AACI,MAAM,UAAU,GAAG,UAAU,CAClC,CACE,EACE,SAAS,EACT,IAAI,EACJ,OAAO,EACP,gBAAgB,GAAG,QAAQ,EAC3B,GAAG,SAAS,EACI,EAClB,GAAG,KACD;IACF,MAAM,iBAAiB,GAAG,UAAU,CAAC,mBAAmB,EAAE,SAAS,CAAC;IAEpE,IAAI,OAAO,EAAE;AACX,QAAA,MAAM,EACJ,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,GAAG,WAAW,EACf,GAAG,SAAS;AAEb,QAAA,QACE,KAAA,CAAA,aAAA,CAAC,OAAO,EAAA,EAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,EAAA,IAAA,EAAA;YAChE,KAAA,CAAA,aAAA,CAAC,UAAU,OACL,WAAW,EAAA,YAAA,EACH,SAAS,IAAI,OAAO,EAChC,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,iBAAiB,EAC5B,GAAG,EAAE,GAAG,EAAA,CACR,CACM;IAEd;AAEA,IAAA,QACE,KAAA,CAAA,aAAA,CAAC,UAAU,OACL,SAAS,EACb,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,iBAAiB,EAC5B,GAAG,EAAE,GAAG,EAAA,CACR;AAEN,CAAC;AAGH,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { DistributiveOmit } from "../../utilities/typeUtils";
|
|
1
2
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
+
import { IconButtonProps } from "./IconButton";
|
|
3
4
|
import { ToggleButtonProps } from "./ToggleButton";
|
|
5
|
+
export type ToggleIconButtonProps = DistributiveOmit<IconButtonProps, "onChange"> & ToggleButtonProps;
|
|
4
6
|
/**
|
|
5
7
|
* An icon-only button that stays either "on" or "off" after each click.
|
|
8
|
+
* Requires an `aria-label` or `tooltip` for accessibility.
|
|
6
9
|
* Maps `pressed` to the native `aria-pressed` attribute, always present
|
|
7
10
|
* since a toggle button must announce that state. Manages its own pressed
|
|
8
11
|
* state, starting from `false`, when `pressed` is omitted — pass
|
|
@@ -13,5 +16,5 @@ import { ToggleButtonProps } from "./ToggleButton";
|
|
|
13
16
|
* @component
|
|
14
17
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-icon-button--docs | Storybook Documentation}
|
|
15
18
|
*/
|
|
16
|
-
export declare const ToggleIconButton: React.ForwardRefExoticComponent<
|
|
19
|
+
export declare const ToggleIconButton: React.ForwardRefExoticComponent<ToggleIconButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
17
20
|
//# sourceMappingURL=ToggleIconButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleIconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/ToggleIconButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAc,
|
|
1
|
+
{"version":3,"file":"ToggleIconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/ToggleIconButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAc,eAAe,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,EACL,iBAAiB,EAGlB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,CAClD,eAAe,EACf,UAAU,CACX,GACC,iBAAiB,CAAA;AAEnB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,iGAkC5B,CAAA"}
|
|
@@ -4,6 +4,7 @@ import { usePressedState, toggleButtonProps } from './ToggleButton.js';
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* An icon-only button that stays either "on" or "off" after each click.
|
|
7
|
+
* Requires an `aria-label` or `tooltip` for accessibility.
|
|
7
8
|
* Maps `pressed` to the native `aria-pressed` attribute, always present
|
|
8
9
|
* since a toggle button must announce that state. Manages its own pressed
|
|
9
10
|
* state, starting from `false`, when `pressed` is omitted — pass
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleIconButton.js","sources":["../../../src/components/button/ToggleIconButton.tsx"],"sourcesContent":["import React, { forwardRef } from \"react\"\n\nimport { IconButton,
|
|
1
|
+
{"version":3,"file":"ToggleIconButton.js","sources":["../../../src/components/button/ToggleIconButton.tsx"],"sourcesContent":["import type { DistributiveOmit } from \"@utilities/typeUtils\"\nimport React, { forwardRef } from \"react\"\n\nimport { IconButton, IconButtonProps } from \"./IconButton\"\nimport {\n ToggleButtonProps,\n toggleButtonProps,\n usePressedState,\n} from \"./ToggleButton\"\n\nexport type ToggleIconButtonProps = DistributiveOmit<\n IconButtonProps,\n \"onChange\"\n> &\n ToggleButtonProps\n\n/**\n * An icon-only button that stays either \"on\" or \"off\" after each click.\n * Requires an `aria-label` or `tooltip` for accessibility.\n * Maps `pressed` to the native `aria-pressed` attribute, always present\n * since a toggle button must announce that state. Manages its own pressed\n * state, starting from `false`, when `pressed` is omitted — pass\n * `defaultPressed` and/or `onChange` to seed or observe that\n * uncontrolled state. Carries no default `kind` or CSS; `kind`/`className`\n * stay exactly as caller-controlled as they are on plain `IconButton`.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-icon-button--docs | Storybook Documentation}\n */\nexport const ToggleIconButton = forwardRef<\n HTMLButtonElement,\n ToggleIconButtonProps\n>(\n (\n {\n defaultPressed,\n onClick,\n onChange,\n pressed,\n ...restProps\n }: ToggleIconButtonProps,\n ref\n ) => {\n const [currentPressed, togglePressed] = usePressedState({\n defaultPressed,\n onChange,\n pressed,\n })\n\n const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {\n togglePressed()\n onClick?.(event)\n }\n\n return (\n <IconButton\n ref={ref}\n {...restProps}\n onClick={handleClick}\n {...toggleButtonProps({ pressed: currentPressed })}\n />\n )\n }\n)\n\nToggleIconButton.displayName = \"ToggleIconButton\"\n"],"names":["React"],"mappings":";;;;AAgBA;;;;;;;;;;;;AAYG;MACU,gBAAgB,GAAG,UAAU,CAIxC,CACE,EACE,cAAc,EACd,OAAO,EACP,QAAQ,EACR,OAAO,EACP,GAAG,SAAS,EACU,EACxB,GAAG,KACD;AACF,IAAA,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,GAAG,eAAe,CAAC;QACtD,cAAc;QACd,QAAQ;QACR,OAAO;AACR,KAAA,CAAC;AAEF,IAAA,MAAM,WAAW,GAA+C,CAAC,KAAK,KAAI;AACxE,QAAA,aAAa,EAAE;AACf,QAAA,OAAO,GAAG,KAAK,CAAC;AAClB,IAAA,CAAC;IAED,QACEA,cAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,GAAG,EAAE,GAAG,EAAA,GACJ,SAAS,EACb,OAAO,EAAE,WAAW,EAAA,GAChB,iBAAiB,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAA,CAClD;AAEN,CAAC;AAGH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB;;;;"}
|
|
@@ -7,10 +7,10 @@ export type { DropdownButtonProps } from "./DropdownButton";
|
|
|
7
7
|
export { DropdownButton } from "./DropdownButton";
|
|
8
8
|
export { DropdownIconButton } from "./DropdownIconButton";
|
|
9
9
|
export type { IconButtonProps } from "./IconButton";
|
|
10
|
-
export type { TooltipPlacement } from "./IconButton";
|
|
11
10
|
export { IconButton } from "./IconButton";
|
|
12
11
|
export type { LoadingButtonProps } from "./LoadingButton";
|
|
13
12
|
export { LoadingButton } from "./LoadingButton";
|
|
14
13
|
export type { PageHeaderActionsDropdownButtonProps } from "./PageHeaderActionsDropdownButton";
|
|
15
14
|
export { PageHeaderActionsDropdownButton } from "./PageHeaderActionsDropdownButton";
|
|
15
|
+
export type { TooltipPlacement } from "../internal/tooltip";
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAElB,YAAY,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAA;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAElB,YAAY,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAA;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,YAAY,EAAE,oCAAoC,EAAE,MAAM,mCAAmC,CAAA;AAC7F,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAA;AACnF,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA"}
|
|
@@ -32,6 +32,8 @@ export interface ComboBoxProps<T extends object = object> {
|
|
|
32
32
|
* Async loading state for the listbox.
|
|
33
33
|
* - `"loading"`: while the collection is empty, replaces the empty state with a spinner.
|
|
34
34
|
* - `"loadingMore"`: shows an inline spinner at the bottom of the listbox (use with `onLoadMore`).
|
|
35
|
+
* - `"filtering"`: renders as `"idle"`, but tells screen reader users "Loading" when results are slow to arrive after typing stops.
|
|
36
|
+
* - `"error"`: renders as `"idle"`, but reads the empty state (`renderEmptyState`) to screen reader users while the collection is empty.
|
|
35
37
|
* - Other values render as `"idle"`.
|
|
36
38
|
*/
|
|
37
39
|
loadingState?: ComboBoxLoadingState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../src/components/combo-box/ComboBox.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAC1B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../src/components/combo-box/ComboBox.tsx"],"names":[],"mappings":"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"}
|
|
@@ -5,10 +5,13 @@ import '../button/DropdownIconButton.js';
|
|
|
5
5
|
import { IconButton } from '../button/IconButton.js';
|
|
6
6
|
import '../button/LoadingButton.js';
|
|
7
7
|
import '../button/PageHeaderActionsDropdownButton.js';
|
|
8
|
+
import { LoadingAnnouncement, LOADING_ANNOUNCEMENT_DELAY_MS } from '../internal/LoadingAnnouncement.js';
|
|
8
9
|
import LoadingSpinner from '../internal/LoadingSpinner.js';
|
|
9
10
|
import Icon from '../../utilities/Icon.js';
|
|
11
|
+
import { useAnnounce } from '../../utilities/useAnnounce.js';
|
|
12
|
+
import { useId } from '../../utilities/useId.js';
|
|
10
13
|
import classNames from 'classnames';
|
|
11
|
-
import React, { useContext } from 'react';
|
|
14
|
+
import React, { useContext, useEffect } from 'react';
|
|
12
15
|
import { ListBoxLoadMoreItem, ComboBox as ComboBox$1, Label, Input, Button, Popover, ListBox, Text, ListBoxItem, ListBoxSection, ComboBoxStateContext, Collection } from 'react-aria-components/ComboBox';
|
|
13
16
|
import { Group } from 'react-aria-components/Group';
|
|
14
17
|
import { Header } from 'react-aria-components/Header';
|
|
@@ -20,6 +23,21 @@ function ClearButton() {
|
|
|
20
23
|
const state = useContext(ComboBoxStateContext);
|
|
21
24
|
return (React.createElement(IconButton, { "aria-label": "Clear", className: "tds-combo-box-clear-button", "data-input-empty": !state?.inputValue ? true : undefined, icon: React.createElement(Icon, { "aria-hidden": true, className: "tds-combo-box-clear-icon", symbol: "general#x" }), kind: "neutral-inline", onClick: () => state?.setInputValue(""), onMouseDown: (event) => event.preventDefault(), tabIndex: -1 }));
|
|
22
25
|
}
|
|
26
|
+
function ErrorAnnouncement({ labelledBy }) {
|
|
27
|
+
const announce = useAnnounce();
|
|
28
|
+
const inputValue = useContext(ComboBoxStateContext)?.inputValue;
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const timeout = setTimeout(() => announce({ "aria-labelledby": labelledBy }), LOADING_ANNOUNCEMENT_DELAY_MS);
|
|
31
|
+
return () => clearTimeout(timeout);
|
|
32
|
+
}, [announce, inputValue, labelledBy]);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function FilteringAnnouncement() {
|
|
36
|
+
const state = useContext(ComboBoxStateContext);
|
|
37
|
+
if (!state?.isOpen)
|
|
38
|
+
return null;
|
|
39
|
+
return React.createElement(LoadingAnnouncement, { key: state.inputValue, message: "Loading" });
|
|
40
|
+
}
|
|
23
41
|
/**
|
|
24
42
|
* A combo box combines a text input with a filterable popover
|
|
25
43
|
* listbox, allowing users to type to search and select from a list of options.
|
|
@@ -34,13 +52,15 @@ function ClearButton() {
|
|
|
34
52
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}
|
|
35
53
|
*/
|
|
36
54
|
function ComboBox({ allowsEmptyCollection = true, children, className, description, disabled, filter, hideLabel, invalid, label, loadingState, menuTrigger = "focus", onChange, onLoadMore, placeholder, readOnly, renderEmptyState = "No results", required, showClearButton, showSearchIcon, size = "md", ...restProps }) {
|
|
55
|
+
const emptyStateId = `tds-combo-box-empty-state-${useId()}`;
|
|
37
56
|
const combinedClassName = classNames("tds-field tds-combo-box", {
|
|
38
57
|
"tds-combo-box--lg": size === "lg",
|
|
39
58
|
"tds-field--lg": size === "lg",
|
|
40
59
|
}, className);
|
|
41
60
|
const loadMoreItem = onLoadMore && (React.createElement(ListBoxLoadMoreItem, { className: "tds-combo-box-load-more", isLoading: loadingState === "loadingMore", onLoadMore: onLoadMore },
|
|
42
|
-
React.createElement("
|
|
43
|
-
|
|
61
|
+
React.createElement("span", { className: "tds-combo-box-loading-label--hidden" }, "Loading more"),
|
|
62
|
+
React.createElement(LoadingSpinner, null),
|
|
63
|
+
React.createElement(LoadingAnnouncement, { message: "Loading more" })));
|
|
44
64
|
const renderChildren = () => {
|
|
45
65
|
if (typeof children === "function") {
|
|
46
66
|
return (React.createElement(Collection, { items: restProps.items ?? restProps.defaultItems }, children));
|
|
@@ -67,10 +87,16 @@ function ComboBox({ allowsEmptyCollection = true, children, className, descripti
|
|
|
67
87
|
!disabled && React.createElement(ClearButton, null)),
|
|
68
88
|
React.createElement(Popover, { className: "tds-combo-box-popover" },
|
|
69
89
|
React.createElement(ListBox, { className: "tds-combo-box-list", renderEmptyState: allowsEmptyCollection
|
|
70
|
-
? () => (React.createElement("div", {
|
|
90
|
+
? () => (React.createElement("div", { className: "tds-combo-box-empty-state", id: emptyStateId },
|
|
91
|
+
loadingState === "error" && (React.createElement(ErrorAnnouncement, { labelledBy: emptyStateId })),
|
|
92
|
+
loadingState === "loading" ? (React.createElement(React.Fragment, null,
|
|
93
|
+
React.createElement("span", { className: "tds-combo-box-loading-label--hidden" }, "Loading"),
|
|
94
|
+
React.createElement(LoadingSpinner, null),
|
|
95
|
+
React.createElement(LoadingAnnouncement, { message: "Loading" }))) : (resolveEmptyState(renderEmptyState))))
|
|
71
96
|
: undefined },
|
|
72
97
|
renderChildren(),
|
|
73
|
-
loadMoreItem)
|
|
98
|
+
loadMoreItem),
|
|
99
|
+
loadingState === "filtering" && React.createElement(FilteringAnnouncement, null)),
|
|
74
100
|
description && (React.createElement(Text, { className: "tds-field-description", slot: "description" },
|
|
75
101
|
React.createElement(Icon, { "aria-hidden": true, className: "tds-field-description-invalid-icon", symbol: "general#exclamation-triangle" }),
|
|
76
102
|
description))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBox.js","sources":["../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import \"../button/btn.css\"\nimport \"../field/index.css\"\nimport \"./index.css\"\n\nimport { IconButton } from \"@components/button\"\nimport LoadingSpinner from \"@components/internal/LoadingSpinner\"\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport classNames from \"classnames\"\nimport React, { type ReactNode, useContext } from \"react\"\nimport {\n Button,\n Collection,\n ComboBox as AriaComboBox,\n type ComboBoxProps as AriaComboBoxProps,\n ComboBoxStateContext,\n Input,\n type Key,\n Label,\n ListBox,\n ListBoxItem,\n type ListBoxItemProps,\n ListBoxLoadMoreItem,\n type ListBoxProps as AriaListBoxProps,\n ListBoxSection,\n type ListBoxSectionProps,\n Popover,\n Text,\n} from \"react-aria-components/ComboBox\"\nimport { Group } from \"react-aria-components/Group\"\nimport { Header } from \"react-aria-components/Header\"\n\nexport type ComboBoxSize = \"md\" | \"lg\"\n\nexport type ComboBoxLoadingState =\n | \"error\"\n | \"filtering\"\n | \"idle\"\n | \"loading\"\n | \"loadingMore\"\n | \"sorting\"\n\ntype ComboBoxChildren<T extends object> = NonNullable<\n AriaListBoxProps<T>[\"children\"]\n>\n\nexport interface ComboBoxProps<T extends object = object> {\n /**\n * If `true`, keeps typed text that does not match an option. Turn it on when\n * ComboBox is a standalone search and the suggestions are shortcuts. Leave it\n * off in forms, where the value needs to match one of the options.\n */\n allowsCustomValue?: boolean\n /** The contents of the listbox. */\n children: ComboBoxChildren<T>\n /** Helper text displayed below the component. Styled as error text when `invalid` is `true`. */\n description?: ReactNode\n /** Disables the field and trigger button. */\n disabled?: boolean\n /** Custom filter function for determining if an item should appear in the list. */\n filter?: (textValue: string, inputValue: string) => boolean\n /** If `true`, the `label` text is rendered as an `aria-label` instead of a visible label element. */\n hideLabel?: boolean\n /** Whether the input is in an invalid state. */\n invalid?: boolean\n /** Accessible label for the field. */\n label: string\n /**\n * Async loading state for the listbox.\n * - `\"loading\"`: while the collection is empty, replaces the empty state with a spinner.\n * - `\"loadingMore\"`: shows an inline spinner at the bottom of the listbox (use with `onLoadMore`).\n * - Other values render as `\"idle\"`.\n */\n loadingState?: ComboBoxLoadingState\n /**\n * The interaction that opens the popover.\n * - `\"input\"`: opens when the user enters text in the input.\n * - `\"focus\"`: opens when the user focuses (via click or keyboard) into the input.\n * - `\"manual\"`: opens only via the trigger button or arrow keys.\n * @default \"focus\"\n */\n menuTrigger?: \"focus\" | \"input\" | \"manual\"\n /**\n * Called when the selected value(s) change.\n * Receives `Key[]` when `selectionMode` is `\"multiple\"`, otherwise `Key | null`.\n */\n onChange?: ((value: Key | null) => void) | ((value: Key[]) => void)\n /** Called when the user scrolls near the bottom of the listbox. Pair with `loadingState` for infinite scroll. */\n onLoadMore?: () => void\n /** Placeholder text for the input. */\n placeholder?: string\n /** If `true`, allows the value to be read but not changed. */\n readOnly?: boolean\n /** Content to display when there are no items in the list. Defaults to \"No results\". */\n renderEmptyState?: ReactNode | (() => ReactNode)\n /** If `true`, appends an asterisk at the end of the label text. */\n required?: boolean\n /**\n * If `true`, renders a button after the input that clears its text. Only\n * applies when `menuTrigger` is `\"focus\"`, where no trigger button is rendered.\n */\n showClearButton?: boolean\n /** If `true`, renders a search icon before the input. */\n showSearchIcon?: boolean\n /** The size of the combo box. */\n size?: ComboBoxSize\n}\n\ntype AriaComboBoxPropsToOmit = \"slot\"\n\ntype AriaComboBoxPropsToInclude =\n | \"allowsEmptyCollection\"\n | \"defaultItems\"\n | \"defaultValue\"\n | \"disabledKeys\"\n | \"inputValue\"\n | \"items\"\n | \"name\"\n | \"onInputChange\"\n | \"selectionMode\"\n | \"value\"\n\nexport type ComboBoxElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n AriaComboBoxProps<T, \"single\" | \"multiple\">,\n ComboBoxProps<T>,\n AriaComboBoxPropsToOmit,\n AriaComboBoxPropsToInclude\n >\n\nfunction resolveEmptyState(value: ReactNode | (() => ReactNode)): ReactNode {\n return typeof value === \"function\" ? value() : value\n}\n\nfunction ClearButton() {\n const state = useContext(ComboBoxStateContext)\n\n return (\n <IconButton\n aria-label=\"Clear\"\n className=\"tds-combo-box-clear-button\"\n data-input-empty={!state?.inputValue ? true : undefined}\n icon={\n <Icon\n aria-hidden\n className=\"tds-combo-box-clear-icon\"\n symbol=\"general#x\"\n />\n }\n kind=\"neutral-inline\"\n onClick={() => state?.setInputValue(\"\")}\n onMouseDown={(event) => event.preventDefault()}\n tabIndex={-1}\n />\n )\n}\n\n/**\n * A combo box combines a text input with a filterable popover\n * listbox, allowing users to type to search and select from a list of options.\n *\n * It supports both single and multiple selection (`selectionMode`), custom filtering,\n * and asynchronous data loading with infinite scroll capabilities (`loadingState` and `onLoadMore`).\n * Collections can be either static or dynamic, managed via the `children`, `items`,\n * or `defaultItems` props. To construct the dropdown list, compose this component\n * with `ComboBoxItem` for individual options and `ComboBoxSection` for grouping.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}\n */\nexport function ComboBox<T extends object>({\n allowsEmptyCollection = true,\n children,\n className,\n description,\n disabled,\n filter,\n hideLabel,\n invalid,\n label,\n loadingState,\n menuTrigger = \"focus\",\n onChange,\n onLoadMore,\n placeholder,\n readOnly,\n renderEmptyState = \"No results\",\n required,\n showClearButton,\n showSearchIcon,\n size = \"md\",\n ...restProps\n}: ComboBoxElementProps<T>) {\n const combinedClassName = classNames(\n \"tds-field tds-combo-box\",\n {\n \"tds-combo-box--lg\": size === \"lg\",\n \"tds-field--lg\": size === \"lg\",\n },\n className\n )\n\n const loadMoreItem = onLoadMore && (\n <ListBoxLoadMoreItem\n className=\"tds-combo-box-load-more\"\n isLoading={loadingState === \"loadingMore\"}\n onLoadMore={onLoadMore}\n >\n <div aria-label=\"Loading more\" role=\"status\">\n <LoadingSpinner />\n </div>\n </ListBoxLoadMoreItem>\n )\n\n const renderChildren = () => {\n if (typeof children === \"function\") {\n return (\n <Collection items={restProps.items ?? restProps.defaultItems}>\n {children}\n </Collection>\n )\n }\n return children\n }\n\n return (\n // React Aria's ComboBox is generic over selection mode (M). We instantiate\n // it with the union \"single\" | \"multiple\" so value/defaultValue/selectionMode\n // accept both shapes. onChange still needs a cast because our type is a union\n // of function types (to allow narrower handlers like\n // `setValue: (Key|null) => void`), which isn't assignable to RAC's\n // single-function signature.\n <AriaComboBox<T, \"single\" | \"multiple\">\n {...restProps}\n allowsEmptyCollection={allowsEmptyCollection}\n aria-label={hideLabel ? label : undefined}\n className={combinedClassName}\n defaultFilter={filter}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n menuTrigger={menuTrigger}\n onChange={onChange as (value: Key | Key[] | null) => void}\n >\n {!hideLabel && <Label className=\"tds-field-label\">{label}</Label>}\n <Group className=\"tds-field-control tds-combo-box-field\">\n {showSearchIcon && (\n <Icon\n aria-hidden\n className=\"tds-combo-box-search-icon\"\n symbol=\"general#search\"\n />\n )}\n <Input\n aria-invalid={invalid || undefined}\n className=\"tds-combo-box-input\"\n placeholder={placeholder}\n />\n {menuTrigger !== \"focus\" && !readOnly && (\n <Button className=\"tds-combo-box-button tds-btn tds-btn--infield\">\n <Icon aria-hidden symbol=\"general#down-caret\" />\n </Button>\n )}\n {showClearButton &&\n menuTrigger === \"focus\" &&\n !readOnly &&\n !disabled && <ClearButton />}\n </Group>\n <Popover className=\"tds-combo-box-popover\">\n <ListBox\n className=\"tds-combo-box-list\"\n renderEmptyState={\n allowsEmptyCollection\n ? () => (\n <div\n aria-label={\n loadingState === \"loading\" ? \"Loading\" : undefined\n }\n className=\"tds-combo-box-empty-state\"\n role={loadingState === \"loading\" ? \"status\" : undefined}\n >\n {loadingState === \"loading\" ? (\n <LoadingSpinner />\n ) : (\n resolveEmptyState(renderEmptyState)\n )}\n </div>\n )\n : undefined\n }\n >\n {renderChildren()}\n {loadMoreItem}\n </ListBox>\n </Popover>\n {description && (\n <Text className=\"tds-field-description\" slot=\"description\">\n <Icon\n aria-hidden\n className=\"tds-field-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </Text>\n )}\n </AriaComboBox>\n )\n}\n\nexport interface ComboBoxItemProps {\n /** Disables the item. */\n disabled?: boolean\n}\n\ntype AriaListBoxItemPropsToOmit = \"isDisabled\"\n\ntype AriaListBoxItemPropsToInclude = \"onAction\" | \"textValue\" | \"value\"\n\nexport type ComboBoxItemElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxItemProps<T>,\n ComboBoxItemProps,\n AriaListBoxItemPropsToOmit,\n AriaListBoxItemPropsToInclude\n >\n\n/**\n * A selectable option within a {@link ComboBox}. Renders as a listbox item.\n *\n * Provide an `id` (or `key` when rendering from a collection) to identify the\n * option, and `textValue` when the visible children are not plain text so\n * type-ahead and screen readers have a stable label to use.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxItem<T extends object>({\n className,\n disabled,\n ...restProps\n}: ComboBoxItemElementProps<T>) {\n return (\n <ListBoxItem\n {...restProps}\n className={classNames(\"tds-combo-box-list-item\", className)}\n isDisabled={disabled}\n />\n )\n}\n\nexport interface ComboBoxSectionProps {\n /** The items rendered within the section. */\n children: ReactNode\n /** Optional heading text rendered above the section's items. */\n title?: string\n}\n\ntype AriaListBoxSectionPropsToInclude = \"dependencies\"\n\nexport type ComboBoxSectionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxSectionProps<T>,\n ComboBoxSectionProps,\n never,\n AriaListBoxSectionPropsToInclude\n >\n\n/**\n * A group of related {@link ComboBoxItem}s within a {@link ComboBox}. Renders\n * an optional `title` heading above its items.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxSection<T extends object>({\n children,\n className,\n title,\n ...restProps\n}: ComboBoxSectionElementProps<T>) {\n return (\n <ListBoxSection\n {...restProps}\n className={classNames(\"tds-combo-box-list-section\", className)}\n >\n {title && (\n <Header className=\"tds-combo-box-section-header\">{title}</Header>\n )}\n {children}\n </ListBoxSection>\n )\n}\n"],"names":["AriaComboBox"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ComboBox.js","sources":["../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import \"../button/btn.css\"\nimport \"../field/index.css\"\nimport \"./index.css\"\n\nimport { IconButton } from \"@components/button\"\nimport {\n LOADING_ANNOUNCEMENT_DELAY_MS,\n LoadingAnnouncement,\n} from \"@components/internal/LoadingAnnouncement\"\nimport LoadingSpinner from \"@components/internal/LoadingSpinner\"\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport { useAnnounce } from \"@utilities/useAnnounce\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { type ReactNode, useContext, useEffect } from \"react\"\nimport {\n Button,\n Collection,\n ComboBox as AriaComboBox,\n type ComboBoxProps as AriaComboBoxProps,\n ComboBoxStateContext,\n Input,\n type Key,\n Label,\n ListBox,\n ListBoxItem,\n type ListBoxItemProps,\n ListBoxLoadMoreItem,\n type ListBoxProps as AriaListBoxProps,\n ListBoxSection,\n type ListBoxSectionProps,\n Popover,\n Text,\n} from \"react-aria-components/ComboBox\"\nimport { Group } from \"react-aria-components/Group\"\nimport { Header } from \"react-aria-components/Header\"\n\nexport type ComboBoxSize = \"md\" | \"lg\"\n\nexport type ComboBoxLoadingState =\n | \"error\"\n | \"filtering\"\n | \"idle\"\n | \"loading\"\n | \"loadingMore\"\n | \"sorting\"\n\ntype ComboBoxChildren<T extends object> = NonNullable<\n AriaListBoxProps<T>[\"children\"]\n>\n\nexport interface ComboBoxProps<T extends object = object> {\n /**\n * If `true`, keeps typed text that does not match an option. Turn it on when\n * ComboBox is a standalone search and the suggestions are shortcuts. Leave it\n * off in forms, where the value needs to match one of the options.\n */\n allowsCustomValue?: boolean\n /** The contents of the listbox. */\n children: ComboBoxChildren<T>\n /** Helper text displayed below the component. Styled as error text when `invalid` is `true`. */\n description?: ReactNode\n /** Disables the field and trigger button. */\n disabled?: boolean\n /** Custom filter function for determining if an item should appear in the list. */\n filter?: (textValue: string, inputValue: string) => boolean\n /** If `true`, the `label` text is rendered as an `aria-label` instead of a visible label element. */\n hideLabel?: boolean\n /** Whether the input is in an invalid state. */\n invalid?: boolean\n /** Accessible label for the field. */\n label: string\n /**\n * Async loading state for the listbox.\n * - `\"loading\"`: while the collection is empty, replaces the empty state with a spinner.\n * - `\"loadingMore\"`: shows an inline spinner at the bottom of the listbox (use with `onLoadMore`).\n * - `\"filtering\"`: renders as `\"idle\"`, but tells screen reader users \"Loading\" when results are slow to arrive after typing stops.\n * - `\"error\"`: renders as `\"idle\"`, but reads the empty state (`renderEmptyState`) to screen reader users while the collection is empty.\n * - Other values render as `\"idle\"`.\n */\n loadingState?: ComboBoxLoadingState\n /**\n * The interaction that opens the popover.\n * - `\"input\"`: opens when the user enters text in the input.\n * - `\"focus\"`: opens when the user focuses (via click or keyboard) into the input.\n * - `\"manual\"`: opens only via the trigger button or arrow keys.\n * @default \"focus\"\n */\n menuTrigger?: \"focus\" | \"input\" | \"manual\"\n /**\n * Called when the selected value(s) change.\n * Receives `Key[]` when `selectionMode` is `\"multiple\"`, otherwise `Key | null`.\n */\n onChange?: ((value: Key | null) => void) | ((value: Key[]) => void)\n /** Called when the user scrolls near the bottom of the listbox. Pair with `loadingState` for infinite scroll. */\n onLoadMore?: () => void\n /** Placeholder text for the input. */\n placeholder?: string\n /** If `true`, allows the value to be read but not changed. */\n readOnly?: boolean\n /** Content to display when there are no items in the list. Defaults to \"No results\". */\n renderEmptyState?: ReactNode | (() => ReactNode)\n /** If `true`, appends an asterisk at the end of the label text. */\n required?: boolean\n /**\n * If `true`, renders a button after the input that clears its text. Only\n * applies when `menuTrigger` is `\"focus\"`, where no trigger button is rendered.\n */\n showClearButton?: boolean\n /** If `true`, renders a search icon before the input. */\n showSearchIcon?: boolean\n /** The size of the combo box. */\n size?: ComboBoxSize\n}\n\ntype AriaComboBoxPropsToOmit = \"slot\"\n\ntype AriaComboBoxPropsToInclude =\n | \"allowsEmptyCollection\"\n | \"defaultItems\"\n | \"defaultValue\"\n | \"disabledKeys\"\n | \"inputValue\"\n | \"items\"\n | \"name\"\n | \"onInputChange\"\n | \"selectionMode\"\n | \"value\"\n\nexport type ComboBoxElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n AriaComboBoxProps<T, \"single\" | \"multiple\">,\n ComboBoxProps<T>,\n AriaComboBoxPropsToOmit,\n AriaComboBoxPropsToInclude\n >\n\nfunction resolveEmptyState(value: ReactNode | (() => ReactNode)): ReactNode {\n return typeof value === \"function\" ? value() : value\n}\n\nfunction ClearButton() {\n const state = useContext(ComboBoxStateContext)\n\n return (\n <IconButton\n aria-label=\"Clear\"\n className=\"tds-combo-box-clear-button\"\n data-input-empty={!state?.inputValue ? true : undefined}\n icon={\n <Icon\n aria-hidden\n className=\"tds-combo-box-clear-icon\"\n symbol=\"general#x\"\n />\n }\n kind=\"neutral-inline\"\n onClick={() => state?.setInputValue(\"\")}\n onMouseDown={(event) => event.preventDefault()}\n tabIndex={-1}\n />\n )\n}\n\nfunction ErrorAnnouncement({ labelledBy }: { labelledBy: string }) {\n const announce = useAnnounce()\n const inputValue = useContext(ComboBoxStateContext)?.inputValue\n\n useEffect(() => {\n const timeout = setTimeout(\n () => announce({ \"aria-labelledby\": labelledBy }),\n LOADING_ANNOUNCEMENT_DELAY_MS\n )\n return () => clearTimeout(timeout)\n }, [announce, inputValue, labelledBy])\n\n return null\n}\n\nfunction FilteringAnnouncement() {\n const state = useContext(ComboBoxStateContext)\n if (!state?.isOpen) return null\n\n return <LoadingAnnouncement key={state.inputValue} message=\"Loading\" />\n}\n\n/**\n * A combo box combines a text input with a filterable popover\n * listbox, allowing users to type to search and select from a list of options.\n *\n * It supports both single and multiple selection (`selectionMode`), custom filtering,\n * and asynchronous data loading with infinite scroll capabilities (`loadingState` and `onLoadMore`).\n * Collections can be either static or dynamic, managed via the `children`, `items`,\n * or `defaultItems` props. To construct the dropdown list, compose this component\n * with `ComboBoxItem` for individual options and `ComboBoxSection` for grouping.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}\n */\nexport function ComboBox<T extends object>({\n allowsEmptyCollection = true,\n children,\n className,\n description,\n disabled,\n filter,\n hideLabel,\n invalid,\n label,\n loadingState,\n menuTrigger = \"focus\",\n onChange,\n onLoadMore,\n placeholder,\n readOnly,\n renderEmptyState = \"No results\",\n required,\n showClearButton,\n showSearchIcon,\n size = \"md\",\n ...restProps\n}: ComboBoxElementProps<T>) {\n const emptyStateId = `tds-combo-box-empty-state-${useId()}`\n const combinedClassName = classNames(\n \"tds-field tds-combo-box\",\n {\n \"tds-combo-box--lg\": size === \"lg\",\n \"tds-field--lg\": size === \"lg\",\n },\n className\n )\n\n const loadMoreItem = onLoadMore && (\n <ListBoxLoadMoreItem\n className=\"tds-combo-box-load-more\"\n isLoading={loadingState === \"loadingMore\"}\n onLoadMore={onLoadMore}\n >\n <span className=\"tds-combo-box-loading-label--hidden\">Loading more</span>\n <LoadingSpinner />\n <LoadingAnnouncement message=\"Loading more\" />\n </ListBoxLoadMoreItem>\n )\n\n const renderChildren = () => {\n if (typeof children === \"function\") {\n return (\n <Collection items={restProps.items ?? restProps.defaultItems}>\n {children}\n </Collection>\n )\n }\n return children\n }\n\n return (\n // React Aria's ComboBox is generic over selection mode (M). We instantiate\n // it with the union \"single\" | \"multiple\" so value/defaultValue/selectionMode\n // accept both shapes. onChange still needs a cast because our type is a union\n // of function types (to allow narrower handlers like\n // `setValue: (Key|null) => void`), which isn't assignable to RAC's\n // single-function signature.\n <AriaComboBox<T, \"single\" | \"multiple\">\n {...restProps}\n allowsEmptyCollection={allowsEmptyCollection}\n aria-label={hideLabel ? label : undefined}\n className={combinedClassName}\n defaultFilter={filter}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n menuTrigger={menuTrigger}\n onChange={onChange as (value: Key | Key[] | null) => void}\n >\n {!hideLabel && <Label className=\"tds-field-label\">{label}</Label>}\n <Group className=\"tds-field-control tds-combo-box-field\">\n {showSearchIcon && (\n <Icon\n aria-hidden\n className=\"tds-combo-box-search-icon\"\n symbol=\"general#search\"\n />\n )}\n <Input\n aria-invalid={invalid || undefined}\n className=\"tds-combo-box-input\"\n placeholder={placeholder}\n />\n {menuTrigger !== \"focus\" && !readOnly && (\n <Button className=\"tds-combo-box-button tds-btn tds-btn--infield\">\n <Icon aria-hidden symbol=\"general#down-caret\" />\n </Button>\n )}\n {showClearButton &&\n menuTrigger === \"focus\" &&\n !readOnly &&\n !disabled && <ClearButton />}\n </Group>\n <Popover className=\"tds-combo-box-popover\">\n <ListBox\n className=\"tds-combo-box-list\"\n renderEmptyState={\n allowsEmptyCollection\n ? () => (\n <div className=\"tds-combo-box-empty-state\" id={emptyStateId}>\n {loadingState === \"error\" && (\n <ErrorAnnouncement labelledBy={emptyStateId} />\n )}\n {loadingState === \"loading\" ? (\n <>\n <span className=\"tds-combo-box-loading-label--hidden\">\n Loading\n </span>\n <LoadingSpinner />\n <LoadingAnnouncement message=\"Loading\" />\n </>\n ) : (\n resolveEmptyState(renderEmptyState)\n )}\n </div>\n )\n : undefined\n }\n >\n {renderChildren()}\n {loadMoreItem}\n </ListBox>\n {loadingState === \"filtering\" && <FilteringAnnouncement />}\n </Popover>\n {description && (\n <Text className=\"tds-field-description\" slot=\"description\">\n <Icon\n aria-hidden\n className=\"tds-field-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </Text>\n )}\n </AriaComboBox>\n )\n}\n\nexport interface ComboBoxItemProps {\n /** Disables the item. */\n disabled?: boolean\n}\n\ntype AriaListBoxItemPropsToOmit = \"isDisabled\"\n\ntype AriaListBoxItemPropsToInclude = \"onAction\" | \"textValue\" | \"value\"\n\nexport type ComboBoxItemElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxItemProps<T>,\n ComboBoxItemProps,\n AriaListBoxItemPropsToOmit,\n AriaListBoxItemPropsToInclude\n >\n\n/**\n * A selectable option within a {@link ComboBox}. Renders as a listbox item.\n *\n * Provide an `id` (or `key` when rendering from a collection) to identify the\n * option, and `textValue` when the visible children are not plain text so\n * type-ahead and screen readers have a stable label to use.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxItem<T extends object>({\n className,\n disabled,\n ...restProps\n}: ComboBoxItemElementProps<T>) {\n return (\n <ListBoxItem\n {...restProps}\n className={classNames(\"tds-combo-box-list-item\", className)}\n isDisabled={disabled}\n />\n )\n}\n\nexport interface ComboBoxSectionProps {\n /** The items rendered within the section. */\n children: ReactNode\n /** Optional heading text rendered above the section's items. */\n title?: string\n}\n\ntype AriaListBoxSectionPropsToInclude = \"dependencies\"\n\nexport type ComboBoxSectionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxSectionProps<T>,\n ComboBoxSectionProps,\n never,\n AriaListBoxSectionPropsToInclude\n >\n\n/**\n * A group of related {@link ComboBoxItem}s within a {@link ComboBox}. Renders\n * an optional `title` heading above its items.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/forms-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxSection<T extends object>({\n children,\n className,\n title,\n ...restProps\n}: ComboBoxSectionElementProps<T>) {\n return (\n <ListBoxSection\n {...restProps}\n className={classNames(\"tds-combo-box-list-section\", className)}\n >\n {title && (\n <Header className=\"tds-combo-box-section-header\">{title}</Header>\n )}\n {children}\n </ListBoxSection>\n )\n}\n"],"names":["AriaComboBox"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/date-picker/DatePicker.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAC1B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,aAAa,CAAA;AAEpB,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,yBAAyB,CAAA;AAEhC,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/date-picker/DatePicker.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAC1B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,aAAa,CAAA;AAEpB,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,yBAAyB,CAAA;AAEhC,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAA;AAGhF,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAA;AAGnE,OAAO,EAUL,KAAK,eAAe,IAAI,mBAAmB,EAM5C,MAAM,kCAAkC,CAAA;AAYzC,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAA;AAExC,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,CAAA;AAepD,MAAM,WAAW,eAAe;IAC9B,4GAA4G;IAC5G,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,wFAAwF;IACxF,YAAY,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAA;IACzC,gGAAgG;IAChG,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,4FAA4F;IAC5F,cAAc,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;IACtE;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,SAAS,CAAA;IACjD,qGAAqG;IACrG,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wFAAwF;IACxF,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAA;IAChD,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,GAAG,CAAC,EAAE,mBAAmB,CAAA;IACzB,uEAAuE;IACvE,GAAG,CAAC,EAAE,mBAAmB,CAAA;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAA;IAC5C,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mCAAmC;IACnC,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,oEAAoE;IACpE,KAAK,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAA;CACnC;AAED,KAAK,yBAAyB,GAC1B,UAAU,GACV,aAAa,GACb,aAAa,GACb,cAAc,GACd,WAAW,GACX,cAAc,GACd,kBAAkB,GAClB,qBAAqB,GACrB,yBAAyB,GACzB,MAAM,CAAA;AAEV,KAAK,4BAA4B,GAAG,QAAQ,GAAG,MAAM,GAAG,cAAc,CAAA;AAEtE,MAAM,MAAM,sBAAsB,GAAG,+BAA+B,CAClE,mBAAmB,CAAC,SAAS,CAAC,EAC9B,eAAe,EACf,yBAAyB,EACzB,4BAA4B,CAC7B,CAAA;AA0QD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,cAAc,EACd,gBAA8C,EAC9C,SAAS,EACT,OAAO,EACP,iBAAiB,EACjB,KAAK,EACL,GAAG,EACH,GAAG,EACH,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,IAAW,EACX,KAAK,EACL,uBAA+B,EAC/B,GAAG,SAAS,EACb,EAAE,sBAAsB,qBA4HxB;yBAjJe,UAAU"}
|