@planningcenter/tapestry 4.8.0 → 4.8.1-qa-1336.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/FilterControls.d.ts.map +1 -1
- package/dist/components/DataTable/FilterControls.js +10 -8
- package/dist/components/DataTable/FilterControls.js.map +1 -1
- package/dist/components/DataTable/FilterControls.module.css.js +1 -1
- package/dist/components/DataTable/TruncatedFilterLabel.d.ts +16 -0
- package/dist/components/DataTable/TruncatedFilterLabel.d.ts.map +1 -0
- package/dist/components/DataTable/TruncatedFilterLabel.js +41 -0
- package/dist/components/DataTable/TruncatedFilterLabel.js.map +1 -0
- package/dist/components/DataTable/numberFilter.d.ts.map +1 -1
- package/dist/components/DataTable/numberFilter.js +49 -31
- package/dist/components/DataTable/numberFilter.js.map +1 -1
- package/dist/components/DataTable/textFilter.js +14 -2
- package/dist/components/DataTable/textFilter.js.map +1 -1
- package/dist/reactRender.css +402 -391
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +402 -391
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/unstable.css +11 -0
- package/dist/unstable.css.map +1 -1
- package/dist/utilities/typeUtils.d.ts +1 -0
- package/dist/utilities/typeUtils.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterControls.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/FilterControls.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAuD,MAAM,OAAO,CAAA;AAY3E,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EAGX,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"FilterControls.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/FilterControls.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAuD,MAAM,OAAO,CAAA;AAY3E,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EAGX,MAAM,eAAe,CAAA;AAmItB,MAAM,WAAW,mBAAmB;IAClC,2FAA2F;IAC3F,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,uDAAuD;IACvD,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,EAC7B,aAAkB,EAClB,OAAO,EACP,eAAuB,EACvB,aAAwB,GACzB,EAAE,mBAAmB,qBAgHrB;yBArHe,cAAc"}
|
|
@@ -20,9 +20,12 @@ import { useAddFilterButtonRef } from './FilterContext.js';
|
|
|
20
20
|
import styles from './FilterControls.module.css.js';
|
|
21
21
|
import { PendingFilterQueue, useQueuePendingFilter, useIsFilterTaken } from './PendingFilterQueue.js';
|
|
22
22
|
import { useSearchableFilters } from './SearchableFilters.js';
|
|
23
|
+
import { TruncatedFilterLabel } from './TruncatedFilterLabel.js';
|
|
23
24
|
import { getDefaultOperatorName } from './utils.js';
|
|
24
25
|
|
|
25
26
|
const NOOP_ACTION = () => { };
|
|
27
|
+
/** Mirrors the `::after` separator in `.search-result-grouping-chevron`. */
|
|
28
|
+
const GROUPING_SEPARATOR = " › ";
|
|
26
29
|
const useVisibleChildren = (group) => {
|
|
27
30
|
const isFilterTaken = useIsFilterTaken();
|
|
28
31
|
return group.children.filter((child) => isFilterNodeVisible(child, isFilterTaken));
|
|
@@ -58,8 +61,7 @@ function FilterItem({ node }) {
|
|
|
58
61
|
name: node.name,
|
|
59
62
|
operator: getDefaultOperatorName(node),
|
|
60
63
|
value: undefined,
|
|
61
|
-
}), textValue: node.label },
|
|
62
|
-
React__default.createElement("span", { slot: "label" }, node.label)));
|
|
64
|
+
}), textValue: node.label }, ({ isFocusVisible, isHovered }) => (React__default.createElement(TruncatedFilterLabel, { active: isFocusVisible || isHovered, text: node.label }))));
|
|
63
65
|
}
|
|
64
66
|
function FilterGroupSection({ group }) {
|
|
65
67
|
const visibleChildren = useVisibleChildren(group);
|
|
@@ -119,17 +121,17 @@ function SearchResultItem({ filter }) {
|
|
|
119
121
|
const resultId = filter.scope
|
|
120
122
|
? `filter-search-${filter.name}-${filter.scope}`
|
|
121
123
|
: `filter-search-${filter.name}`;
|
|
124
|
+
const visibleLabel = [...remainingGrouping, filter.label].join(GROUPING_SEPARATOR);
|
|
122
125
|
return (React__default.createElement(DropdownAction, { key: resultId, textValue: filter.searchable, id: resultId, onAction: () => queuePendingFilter({
|
|
123
126
|
name: filter.name,
|
|
124
127
|
operator: filter.operator,
|
|
125
128
|
scope: filter.scope,
|
|
126
129
|
value: undefined,
|
|
127
|
-
}) },
|
|
128
|
-
React__default.createElement("span", {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
filter.label)));
|
|
130
|
+
}) }, ({ isFocusVisible, isHovered }) => (React__default.createElement(TruncatedFilterLabel, { active: isFocusVisible || isHovered, text: visibleLabel },
|
|
131
|
+
remainingGrouping.length > 0 && (React__default.createElement("span", { className: styles["search-result-grouping"] }, remainingGrouping.map((grouping, index) => (React__default.createElement("span", { className: styles["search-result-grouping-chevron"], key: `${grouping}-${index}` },
|
|
132
|
+
grouping,
|
|
133
|
+
React__default.createElement("span", { className: styles["search-result-grouping-separator"] }, ", ")))))),
|
|
134
|
+
filter.label))));
|
|
133
135
|
}
|
|
134
136
|
function SearchResults() {
|
|
135
137
|
const filters = useSearchableFilters();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterControls.js","sources":["../../../src/components/DataTable/FilterControls.tsx"],"sourcesContent":["import { Button, IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport { DropdownAction, DropdownSection } from \"@components/dropdown\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@components/popover\"\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { type ReactElement, useMemo, useRef, useState } from \"react\"\nimport { Autocomplete, SearchField } from \"react-aria-components\"\nimport { Input } from \"react-aria-components/Input\"\nimport { Label } from \"react-aria-components/Label\"\nimport {\n Menu,\n Popover as AriaPopover,\n SubmenuTrigger,\n} from \"react-aria-components/Menu\"\n\nimport { useAddFilterButtonRef } from \"./FilterContext\"\nimport styles from \"./FilterControls.module.css\"\nimport type {\n ActiveFilter,\n FilterNode,\n FilterNodeGroup,\n FilterNodeItem,\n} from \"./FilterTypes\"\nimport {\n PendingFilterQueue,\n useIsFilterTaken,\n useQueuePendingFilter,\n} from \"./PendingFilterQueue\"\nimport type { SearchableSimpleFilterItem } from \"./SearchableFilters\"\nimport { useSearchableFilters } from \"./SearchableFilters\"\nimport { getDefaultOperatorName } from \"./utils\"\n\nconst NOOP_ACTION = () => {}\n\nconst useVisibleChildren = (group: FilterNodeGroup) => {\n const isFilterTaken = useIsFilterTaken()\n return group.children.filter((child) =>\n isFilterNodeVisible(child, isFilterTaken)\n )\n}\n\nfunction isFilterNodeVisible(\n node: FilterNode,\n isFilterTaken: (name: string) => boolean\n): boolean {\n if (node.children) {\n return node.children.some((child) =>\n isFilterNodeVisible(child, isFilterTaken)\n )\n }\n\n return node.allowMultiple || !isFilterTaken(node.name)\n}\n\n// Must be a dedicated component, not returned inline from `renderFilterItem`.\n// RAC clones an `id` onto whatever that function returns, and an inline\n// `SubmenuTrigger` has none of its own — the clone falls back to `item.id`,\n// colliding with the trigger child's own `id` and silently breaking it.\nfunction FilterSubmenu({ group }: { group: FilterNodeGroup }) {\n const visibleChildren = useVisibleChildren(group)\n\n if (visibleChildren.length === 0) return null\n\n return (\n <SubmenuTrigger>\n <DropdownAction\n className=\"tds-data-table-filter-controls-submenu-trigger\"\n id={group.label}\n onAction={NOOP_ACTION}\n textValue={group.label}\n >\n <span slot=\"label\">{group.label}</span>\n <Icon\n aria-hidden\n className=\"tds-data-table-filter-controls-submenu-chevron\"\n slot=\"suffix\"\n symbol=\"general#right-chevron\"\n />\n </DropdownAction>\n <AriaPopover\n className=\"tds-dropdown-popover tds-data-table-filter-controls-submenu-popover\"\n placement=\"right top\"\n >\n <Menu\n aria-label={group.label}\n className=\"tds-data-table-filter-controls-submenu-list\"\n items={visibleChildren}\n >\n {renderFilterItem}\n </Menu>\n </AriaPopover>\n </SubmenuTrigger>\n )\n}\n\nfunction FilterItem({ node }: { node: FilterNodeItem }) {\n const queuePendingFilter = useQueuePendingFilter()\n const isFilterTaken = useIsFilterTaken()\n const hide = !node.allowMultiple && isFilterTaken(node.name)\n\n if (hide) return null\n\n return (\n <DropdownAction\n key={node.name}\n id={node.name}\n onAction={() =>\n queuePendingFilter({\n name: node.name,\n operator: getDefaultOperatorName(node),\n value: undefined,\n })\n }\n textValue={node.label}\n >\n <span slot=\"label\">{node.label}</span>\n </DropdownAction>\n )\n}\n\nfunction FilterGroupSection({ group }: { group: FilterNodeGroup }) {\n const visibleChildren = useVisibleChildren(group)\n\n if (visibleChildren.length === 0) return null\n\n return (\n <DropdownSection id={group.label} title={group.label}>\n {visibleChildren.map(renderFilterItem)}\n </DropdownSection>\n )\n}\n\nfunction renderFilterItem(node: FilterNode): ReactElement {\n if (node.children) {\n if (node.renderChildrenInSubmenu) {\n return <FilterSubmenu key={node.label} group={node} />\n }\n\n return <FilterGroupSection key={node.label} group={node} />\n }\n\n return <FilterItem key={node.name} node={node} />\n}\n\nexport interface FilterControlsProps {\n /** The currently active filters. The toggle button only renders when this is non-empty. */\n activeFilters?: ActiveFilter[]\n filters: FilterNode[]\n /** Whether the filters shelf is currently expanded. */\n isShelfExpanded?: boolean\n /** Called when the toggle button is pressed. */\n onToggleShelf?: () => void\n}\n\n/** Skeleton for the DataTable filters cluster — grows incrementally. */\nexport function FilterControls({\n activeFilters = [],\n filters,\n isShelfExpanded = false,\n onToggleShelf = () => {},\n}: FilterControlsProps) {\n const searchInputId = `tds-data-table-filter-controls-search-${useId()}`\n const [searchQuery, setSearchQuery] = useState(\"\")\n const addFilterButtonRef = useAddFilterButtonRef()\n const searchInputRef = useRef<HTMLInputElement | null>(null)\n\n return (\n <ButtonGroup\n aria-label=\"Filters\"\n className=\"tds-data-table-filter-controls\"\n >\n <Popover\n onOpenChange={(open) => {\n if (open) setSearchQuery(\"\")\n }}\n >\n <PopoverTrigger>\n <Button\n ref={addFilterButtonRef}\n label=\"Add filter\"\n prefix={\n <Icon\n aria-hidden\n symbol=\"general#three-reducing-horizontal-bars\"\n />\n }\n />\n </PopoverTrigger>\n <PopoverContent className=\"tds-data-table-popover\" placement=\"bottom\">\n <PendingFilterQueue>\n <Autocomplete\n filter={prefixSearch}\n inputValue={searchQuery}\n onInputChange={setSearchQuery}\n >\n <SearchField className=\"tds-data-table-filter-controls-search-input-sticky\">\n <Label\n className=\"tds-data-table-filter-controls-label--hidden\"\n htmlFor={searchInputId}\n >\n Search filters\n </Label>\n <div\n className={classNames(\n \"tds-data-table-filter-controls-search-input-control\",\n {\n \"tds-data-table-filter-controls-search-input-control--has-value\":\n searchQuery.length > 0,\n }\n )}\n >\n <Icon\n aria-hidden\n className=\"tds-data-table-filter-controls-search-input-icon\"\n symbol=\"general#search\"\n />\n <Input\n id={searchInputId}\n placeholder=\"Search filters\"\n className=\"tds-data-table-filter-controls-search-input\"\n ref={searchInputRef}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n <IconButton\n aria-label=\"Clear\"\n icon={\n <Icon\n aria-hidden\n className=\"tds-data-table-filter-controls-search-input-clear-icon\"\n symbol=\"general#x\"\n />\n }\n kind=\"neutral-inline\"\n onClick={() => {\n setSearchQuery(\"\")\n searchInputRef.current?.focus()\n }}\n tabIndex={-1}\n />\n </div>\n </SearchField>\n <Menu\n aria-label=\"Filters\"\n items={filters}\n className=\"tds-data-table-filter-controls-list\"\n renderEmptyState={() => (\n <span className=\"tds-dropdown-item\">No filters match</span>\n )}\n >\n {searchQuery.length ? <SearchResults /> : renderFilterItem}\n </Menu>\n </Autocomplete>\n </PendingFilterQueue>\n </PopoverContent>\n </Popover>\n {activeFilters.length > 0 && (\n <Button\n aria-expanded={isShelfExpanded}\n aria-label={`${activeFilters.length} active filter${\n activeFilters.length === 1 ? \"\" : \"s\"\n }`}\n label={\n <span className=\"tds-data-table-filter-controls-badge\">\n {activeFilters.length}\n </span>\n }\n onClick={onToggleShelf}\n />\n )}\n </ButtonGroup>\n )\n}\n\nFilterControls.displayName = \"FilterControls\"\n\nfunction SearchResultItem({ filter }: { filter: SearchableSimpleFilterItem }) {\n const queuePendingFilter = useQueuePendingFilter()\n const isFilterTaken = useIsFilterTaken()\n const hide = !filter.allowMultiple && isFilterTaken(filter.name)\n\n if (hide) return null\n\n const [, ...remainingGrouping] = filter.grouping\n const resultId = filter.scope\n ? `filter-search-${filter.name}-${filter.scope}`\n : `filter-search-${filter.name}`\n\n return (\n <DropdownAction\n key={resultId}\n textValue={filter.searchable}\n id={resultId}\n onAction={() =>\n queuePendingFilter({\n name: filter.name,\n operator: filter.operator,\n scope: filter.scope,\n value: undefined,\n })\n }\n >\n <span slot=\"label\">\n {remainingGrouping.length > 0 && (\n <span className={styles[\"search-result-grouping\"]}>\n {remainingGrouping.map((grouping, index) => (\n <span\n className={styles[\"search-result-grouping-chevron\"]}\n key={`${grouping}-${index}`}\n >\n {grouping}\n <span className={styles[\"search-result-grouping-separator\"]}>\n {\", \"}\n </span>\n </span>\n ))}\n </span>\n )}\n {filter.label}\n </span>\n </DropdownAction>\n )\n}\n\nfunction SearchResults() {\n const filters = useSearchableFilters()\n\n const { groups, ungrouped } = useMemo(() => {\n const ungroupedItems = filters.filter((f) => f.grouping.length === 0)\n const groupedItems = new Map<string, SearchableSimpleFilterItem[]>()\n filters.forEach((filter) => {\n const [heading] = filter.grouping\n if (!heading) return\n groupedItems.set(heading, [...(groupedItems.get(heading) ?? []), filter])\n })\n return { groups: groupedItems, ungrouped: ungroupedItems }\n }, [filters])\n\n return (\n <>\n {ungrouped.map((filter) => (\n <SearchResultItem\n key={filter.scope ? `${filter.name}-${filter.scope}` : filter.name}\n filter={filter}\n />\n ))}\n {Array.from(groups, ([groupLabel, items]) => (\n <DropdownSection key={groupLabel} id={groupLabel} title={groupLabel}>\n {items.map((filter) => (\n <SearchResultItem\n key={\n filter.scope ? `${filter.name}-${filter.scope}` : filter.name\n }\n filter={filter}\n />\n ))}\n </DropdownSection>\n ))}\n </>\n )\n}\n\nfunction prefixSearch(string: string, query: string): boolean {\n if (query.length === 0) {\n return true\n }\n\n const segments = query.normalize(\"NFC\").toLowerCase().split(/\\s+/)\n return segments.every((segment) => string.includes(segment))\n}\n"],"names":["React","AriaPopover"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilterControls.js","sources":["../../../src/components/DataTable/FilterControls.tsx"],"sourcesContent":["import { Button, IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport { DropdownAction, DropdownSection } from \"@components/dropdown\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@components/popover\"\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { type ReactElement, useMemo, useRef, useState } from \"react\"\nimport { Autocomplete, SearchField } from \"react-aria-components\"\nimport { Input } from \"react-aria-components/Input\"\nimport { Label } from \"react-aria-components/Label\"\nimport {\n Menu,\n Popover as AriaPopover,\n SubmenuTrigger,\n} from \"react-aria-components/Menu\"\n\nimport { useAddFilterButtonRef } from \"./FilterContext\"\nimport styles from \"./FilterControls.module.css\"\nimport type {\n ActiveFilter,\n FilterNode,\n FilterNodeGroup,\n FilterNodeItem,\n} from \"./FilterTypes\"\nimport {\n PendingFilterQueue,\n useIsFilterTaken,\n useQueuePendingFilter,\n} from \"./PendingFilterQueue\"\nimport type { SearchableSimpleFilterItem } from \"./SearchableFilters\"\nimport { useSearchableFilters } from \"./SearchableFilters\"\nimport { TruncatedFilterLabel } from \"./TruncatedFilterLabel\"\nimport { getDefaultOperatorName } from \"./utils\"\n\nconst NOOP_ACTION = () => {}\n\n/** Mirrors the `::after` separator in `.search-result-grouping-chevron`. */\nconst GROUPING_SEPARATOR = \" › \"\n\nconst useVisibleChildren = (group: FilterNodeGroup) => {\n const isFilterTaken = useIsFilterTaken()\n return group.children.filter((child) =>\n isFilterNodeVisible(child, isFilterTaken)\n )\n}\n\nfunction isFilterNodeVisible(\n node: FilterNode,\n isFilterTaken: (name: string) => boolean\n): boolean {\n if (node.children) {\n return node.children.some((child) =>\n isFilterNodeVisible(child, isFilterTaken)\n )\n }\n\n return node.allowMultiple || !isFilterTaken(node.name)\n}\n\n// Must be a dedicated component, not returned inline from `renderFilterItem`.\n// RAC clones an `id` onto whatever that function returns, and an inline\n// `SubmenuTrigger` has none of its own — the clone falls back to `item.id`,\n// colliding with the trigger child's own `id` and silently breaking it.\nfunction FilterSubmenu({ group }: { group: FilterNodeGroup }) {\n const visibleChildren = useVisibleChildren(group)\n\n if (visibleChildren.length === 0) return null\n\n return (\n <SubmenuTrigger>\n <DropdownAction\n className=\"tds-data-table-filter-controls-submenu-trigger\"\n id={group.label}\n onAction={NOOP_ACTION}\n textValue={group.label}\n >\n <span slot=\"label\">{group.label}</span>\n <Icon\n aria-hidden\n className=\"tds-data-table-filter-controls-submenu-chevron\"\n slot=\"suffix\"\n symbol=\"general#right-chevron\"\n />\n </DropdownAction>\n <AriaPopover\n className=\"tds-dropdown-popover tds-data-table-filter-controls-submenu-popover\"\n placement=\"right top\"\n >\n <Menu\n aria-label={group.label}\n className=\"tds-data-table-filter-controls-submenu-list\"\n items={visibleChildren}\n >\n {renderFilterItem}\n </Menu>\n </AriaPopover>\n </SubmenuTrigger>\n )\n}\n\nfunction FilterItem({ node }: { node: FilterNodeItem }) {\n const queuePendingFilter = useQueuePendingFilter()\n const isFilterTaken = useIsFilterTaken()\n const hide = !node.allowMultiple && isFilterTaken(node.name)\n\n if (hide) return null\n\n return (\n <DropdownAction\n key={node.name}\n id={node.name}\n onAction={() =>\n queuePendingFilter({\n name: node.name,\n operator: getDefaultOperatorName(node),\n value: undefined,\n })\n }\n textValue={node.label}\n >\n {({ isFocusVisible, isHovered }) => (\n <TruncatedFilterLabel\n active={isFocusVisible || isHovered}\n text={node.label}\n />\n )}\n </DropdownAction>\n )\n}\n\nfunction FilterGroupSection({ group }: { group: FilterNodeGroup }) {\n const visibleChildren = useVisibleChildren(group)\n\n if (visibleChildren.length === 0) return null\n\n return (\n <DropdownSection id={group.label} title={group.label}>\n {visibleChildren.map(renderFilterItem)}\n </DropdownSection>\n )\n}\n\nfunction renderFilterItem(node: FilterNode): ReactElement {\n if (node.children) {\n if (node.renderChildrenInSubmenu) {\n return <FilterSubmenu key={node.label} group={node} />\n }\n\n return <FilterGroupSection key={node.label} group={node} />\n }\n\n return <FilterItem key={node.name} node={node} />\n}\n\nexport interface FilterControlsProps {\n /** The currently active filters. The toggle button only renders when this is non-empty. */\n activeFilters?: ActiveFilter[]\n filters: FilterNode[]\n /** Whether the filters shelf is currently expanded. */\n isShelfExpanded?: boolean\n /** Called when the toggle button is pressed. */\n onToggleShelf?: () => void\n}\n\n/** Skeleton for the DataTable filters cluster — grows incrementally. */\nexport function FilterControls({\n activeFilters = [],\n filters,\n isShelfExpanded = false,\n onToggleShelf = () => {},\n}: FilterControlsProps) {\n const searchInputId = `tds-data-table-filter-controls-search-${useId()}`\n const [searchQuery, setSearchQuery] = useState(\"\")\n const addFilterButtonRef = useAddFilterButtonRef()\n const searchInputRef = useRef<HTMLInputElement | null>(null)\n\n return (\n <ButtonGroup\n aria-label=\"Filters\"\n className=\"tds-data-table-filter-controls\"\n >\n <Popover\n onOpenChange={(open) => {\n if (open) setSearchQuery(\"\")\n }}\n >\n <PopoverTrigger>\n <Button\n ref={addFilterButtonRef}\n label=\"Add filter\"\n prefix={\n <Icon\n aria-hidden\n symbol=\"general#three-reducing-horizontal-bars\"\n />\n }\n />\n </PopoverTrigger>\n <PopoverContent className=\"tds-data-table-popover\" placement=\"bottom\">\n <PendingFilterQueue>\n <Autocomplete\n filter={prefixSearch}\n inputValue={searchQuery}\n onInputChange={setSearchQuery}\n >\n <SearchField className=\"tds-data-table-filter-controls-search-input-sticky\">\n <Label\n className=\"tds-data-table-filter-controls-label--hidden\"\n htmlFor={searchInputId}\n >\n Search filters\n </Label>\n <div\n className={classNames(\n \"tds-data-table-filter-controls-search-input-control\",\n {\n \"tds-data-table-filter-controls-search-input-control--has-value\":\n searchQuery.length > 0,\n }\n )}\n >\n <Icon\n aria-hidden\n className=\"tds-data-table-filter-controls-search-input-icon\"\n symbol=\"general#search\"\n />\n <Input\n id={searchInputId}\n placeholder=\"Search filters\"\n className=\"tds-data-table-filter-controls-search-input\"\n ref={searchInputRef}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n <IconButton\n aria-label=\"Clear\"\n icon={\n <Icon\n aria-hidden\n className=\"tds-data-table-filter-controls-search-input-clear-icon\"\n symbol=\"general#x\"\n />\n }\n kind=\"neutral-inline\"\n onClick={() => {\n setSearchQuery(\"\")\n searchInputRef.current?.focus()\n }}\n tabIndex={-1}\n />\n </div>\n </SearchField>\n <Menu\n aria-label=\"Filters\"\n items={filters}\n className=\"tds-data-table-filter-controls-list\"\n renderEmptyState={() => (\n <span className=\"tds-dropdown-item\">No filters match</span>\n )}\n >\n {searchQuery.length ? <SearchResults /> : renderFilterItem}\n </Menu>\n </Autocomplete>\n </PendingFilterQueue>\n </PopoverContent>\n </Popover>\n {activeFilters.length > 0 && (\n <Button\n aria-expanded={isShelfExpanded}\n aria-label={`${activeFilters.length} active filter${\n activeFilters.length === 1 ? \"\" : \"s\"\n }`}\n label={\n <span className=\"tds-data-table-filter-controls-badge\">\n {activeFilters.length}\n </span>\n }\n onClick={onToggleShelf}\n />\n )}\n </ButtonGroup>\n )\n}\n\nFilterControls.displayName = \"FilterControls\"\n\nfunction SearchResultItem({ filter }: { filter: SearchableSimpleFilterItem }) {\n const queuePendingFilter = useQueuePendingFilter()\n const isFilterTaken = useIsFilterTaken()\n const hide = !filter.allowMultiple && isFilterTaken(filter.name)\n\n if (hide) return null\n\n const [, ...remainingGrouping] = filter.grouping\n const resultId = filter.scope\n ? `filter-search-${filter.name}-${filter.scope}`\n : `filter-search-${filter.name}`\n const visibleLabel = [...remainingGrouping, filter.label].join(\n GROUPING_SEPARATOR\n )\n\n return (\n <DropdownAction\n key={resultId}\n textValue={filter.searchable}\n id={resultId}\n onAction={() =>\n queuePendingFilter({\n name: filter.name,\n operator: filter.operator,\n scope: filter.scope,\n value: undefined,\n })\n }\n >\n {({ isFocusVisible, isHovered }) => (\n <TruncatedFilterLabel\n active={isFocusVisible || isHovered}\n text={visibleLabel}\n >\n {remainingGrouping.length > 0 && (\n <span className={styles[\"search-result-grouping\"]}>\n {remainingGrouping.map((grouping, index) => (\n <span\n className={styles[\"search-result-grouping-chevron\"]}\n key={`${grouping}-${index}`}\n >\n {grouping}\n <span className={styles[\"search-result-grouping-separator\"]}>\n {\", \"}\n </span>\n </span>\n ))}\n </span>\n )}\n {filter.label}\n </TruncatedFilterLabel>\n )}\n </DropdownAction>\n )\n}\n\nfunction SearchResults() {\n const filters = useSearchableFilters()\n\n const { groups, ungrouped } = useMemo(() => {\n const ungroupedItems = filters.filter((f) => f.grouping.length === 0)\n const groupedItems = new Map<string, SearchableSimpleFilterItem[]>()\n filters.forEach((filter) => {\n const [heading] = filter.grouping\n if (!heading) return\n groupedItems.set(heading, [...(groupedItems.get(heading) ?? []), filter])\n })\n return { groups: groupedItems, ungrouped: ungroupedItems }\n }, [filters])\n\n return (\n <>\n {ungrouped.map((filter) => (\n <SearchResultItem\n key={filter.scope ? `${filter.name}-${filter.scope}` : filter.name}\n filter={filter}\n />\n ))}\n {Array.from(groups, ([groupLabel, items]) => (\n <DropdownSection key={groupLabel} id={groupLabel} title={groupLabel}>\n {items.map((filter) => (\n <SearchResultItem\n key={\n filter.scope ? `${filter.name}-${filter.scope}` : filter.name\n }\n filter={filter}\n />\n ))}\n </DropdownSection>\n ))}\n </>\n )\n}\n\nfunction prefixSearch(string: string, query: string): boolean {\n if (query.length === 0) {\n return true\n }\n\n const segments = query.normalize(\"NFC\").toLowerCase().split(/\\s+/)\n return segments.every((segment) => string.includes(segment))\n}\n"],"names":["React","AriaPopover"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var styles = {"search-result-grouping":"search-result-grouping-4F5Lx","search-result-grouping-chevron":"search-result-grouping-chevron--AUkV","search-result-grouping-separator":"search-result-grouping-separator-dKnTA"};
|
|
1
|
+
var styles = {"search-result-grouping":"search-result-grouping-4F5Lx","search-result-grouping-chevron":"search-result-grouping-chevron--AUkV","search-result-grouping-separator":"search-result-grouping-separator-dKnTA","truncation-tooltip":"truncation-tooltip-q6xkT"};
|
|
2
2
|
|
|
3
3
|
export { styles as default };
|
|
4
4
|
//# sourceMappingURL=FilterControls.module.css.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A filter menu item's label, with a tooltip repeating the full text when it
|
|
4
|
+
* is too long to fit. The tooltip is hidden from assistive tech — the
|
|
5
|
+
* untruncated label is already the item's accessible name, so announcing it
|
|
6
|
+
* again would be redundant.
|
|
7
|
+
*/
|
|
8
|
+
export declare function TruncatedFilterLabel({ active, children, text, }: {
|
|
9
|
+
/** Whether the owning menu item is hovered or focused. */
|
|
10
|
+
active: boolean;
|
|
11
|
+
/** Label markup. Defaults to `text` when omitted. */
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/** The full label, shown in the tooltip when the visible label is clipped. */
|
|
14
|
+
text: string;
|
|
15
|
+
}): React.JSX.Element;
|
|
16
|
+
//# sourceMappingURL=TruncatedFilterLabel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TruncatedFilterLabel.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/TruncatedFilterLabel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,KAAK,SAAS,EAKf,MAAM,OAAO,CAAA;AAad;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,QAAQ,EACR,IAAI,GACL,EAAE;IACD,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAA;IACf,qDAAqD;IACrD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAA;CACb,qBAgBA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React__default, { useRef, useState, useLayoutEffect } from 'react';
|
|
2
|
+
import { Overlay } from 'react-aria/Overlay';
|
|
3
|
+
import { useOverlayPosition } from 'react-aria/useOverlayPosition';
|
|
4
|
+
import styles from './FilterControls.module.css.js';
|
|
5
|
+
|
|
6
|
+
const TRUNCATION_TOLERANCE = 1;
|
|
7
|
+
const TOOLTIP_OFFSET = 12;
|
|
8
|
+
function isTruncated(el) {
|
|
9
|
+
return !!el && el.scrollWidth - el.clientWidth > TRUNCATION_TOLERANCE;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A filter menu item's label, with a tooltip repeating the full text when it
|
|
13
|
+
* is too long to fit. The tooltip is hidden from assistive tech — the
|
|
14
|
+
* untruncated label is already the item's accessible name, so announcing it
|
|
15
|
+
* again would be redundant.
|
|
16
|
+
*/
|
|
17
|
+
function TruncatedFilterLabel({ active, children, text, }) {
|
|
18
|
+
const labelRef = useRef(null);
|
|
19
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
20
|
+
useLayoutEffect(() => {
|
|
21
|
+
setIsOpen(active && isTruncated(labelRef.current));
|
|
22
|
+
}, [active, text]);
|
|
23
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
24
|
+
React__default.createElement("span", { ref: labelRef, slot: "label" }, children ?? text),
|
|
25
|
+
isOpen && React__default.createElement(LabelTooltip, { targetRef: labelRef, text: text })));
|
|
26
|
+
}
|
|
27
|
+
function LabelTooltip({ targetRef, text, }) {
|
|
28
|
+
const overlayRef = useRef(null);
|
|
29
|
+
const { overlayProps } = useOverlayPosition({
|
|
30
|
+
isOpen: true,
|
|
31
|
+
offset: TOOLTIP_OFFSET,
|
|
32
|
+
overlayRef,
|
|
33
|
+
placement: "bottom",
|
|
34
|
+
targetRef,
|
|
35
|
+
});
|
|
36
|
+
return (React__default.createElement(Overlay, { disableFocusManagement: true },
|
|
37
|
+
React__default.createElement("div", { ...overlayProps, ref: overlayRef, "aria-hidden": true, className: styles["truncation-tooltip"] }, text)));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { TruncatedFilterLabel };
|
|
41
|
+
//# sourceMappingURL=TruncatedFilterLabel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TruncatedFilterLabel.js","sources":["../../../src/components/DataTable/TruncatedFilterLabel.tsx"],"sourcesContent":["import React, {\n type ReactNode,\n type RefObject,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\"\nimport { Overlay } from \"react-aria/Overlay\"\nimport { useOverlayPosition } from \"react-aria/useOverlayPosition\"\n\nimport styles from \"./FilterControls.module.css\"\n\nconst TRUNCATION_TOLERANCE = 1\nconst TOOLTIP_OFFSET = 12\n\nfunction isTruncated(el: HTMLElement | null) {\n return !!el && el.scrollWidth - el.clientWidth > TRUNCATION_TOLERANCE\n}\n\n/**\n * A filter menu item's label, with a tooltip repeating the full text when it\n * is too long to fit. The tooltip is hidden from assistive tech — the\n * untruncated label is already the item's accessible name, so announcing it\n * again would be redundant.\n */\nexport function TruncatedFilterLabel({\n active,\n children,\n text,\n}: {\n /** Whether the owning menu item is hovered or focused. */\n active: boolean\n /** Label markup. Defaults to `text` when omitted. */\n children?: ReactNode\n /** The full label, shown in the tooltip when the visible label is clipped. */\n text: string\n}) {\n const labelRef = useRef<HTMLSpanElement>(null)\n const [isOpen, setIsOpen] = useState(false)\n\n useLayoutEffect(() => {\n setIsOpen(active && isTruncated(labelRef.current))\n }, [active, text])\n\n return (\n <>\n <span ref={labelRef} slot=\"label\">\n {children ?? text}\n </span>\n {isOpen && <LabelTooltip targetRef={labelRef} text={text} />}\n </>\n )\n}\n\nfunction LabelTooltip({\n targetRef,\n text,\n}: {\n targetRef: RefObject<HTMLElement>\n text: string\n}) {\n const overlayRef = useRef<HTMLDivElement>(null)\n const { overlayProps } = useOverlayPosition({\n isOpen: true,\n offset: TOOLTIP_OFFSET,\n overlayRef,\n placement: \"bottom\",\n targetRef,\n })\n\n return (\n <Overlay disableFocusManagement>\n <div\n {...overlayProps}\n ref={overlayRef}\n aria-hidden\n className={styles[\"truncation-tooltip\"]}\n >\n {text}\n </div>\n </Overlay>\n )\n}\n"],"names":["React"],"mappings":";;;;;AAYA,MAAM,oBAAoB,GAAG,CAAC;AAC9B,MAAM,cAAc,GAAG,EAAE;AAEzB,SAAS,WAAW,CAAC,EAAsB,EAAA;AACzC,IAAA,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,WAAW,GAAG,oBAAoB;AACvE;AAEA;;;;;AAKG;AACG,SAAU,oBAAoB,CAAC,EACnC,MAAM,EACN,QAAQ,EACR,IAAI,GAQL,EAAA;AACC,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAkB,IAAI,CAAC;IAC9C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAE3C,eAAe,CAAC,MAAK;QACnB,SAAS,CAAC,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACpD,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAElB,IAAA,QACEA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA;QACEA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAM,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAC,OAAO,EAAA,EAC9B,QAAQ,IAAI,IAAI,CACZ;AACN,QAAA,MAAM,IAAIA,cAAA,CAAA,aAAA,CAAC,YAAY,EAAA,EAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAA,CAAI,CAC3D;AAEP;AAEA,SAAS,YAAY,CAAC,EACpB,SAAS,EACT,IAAI,GAIL,EAAA;AACC,IAAA,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC;AAC/C,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,kBAAkB,CAAC;AAC1C,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,MAAM,EAAE,cAAc;QACtB,UAAU;AACV,QAAA,SAAS,EAAE,QAAQ;QACnB,SAAS;AACV,KAAA,CAAC;AAEF,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,OAAO,EAAA,EAAC,sBAAsB,EAAA,IAAA,EAAA;AAC7B,QAAAA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GACM,YAAY,EAChB,GAAG,EAAE,UAAU,uBAEf,SAAS,EAAE,MAAM,CAAC,oBAAoB,CAAC,EAAA,EAEtC,IAAI,CACD,CACE;AAEd;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/numberFilter.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"numberFilter.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/numberFilter.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAEf,MAAM,eAAe,CAAA;AAGtB,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEzD,eAAO,MAAM,GAAG;;;;;;CAIa,CAAA;AAC7B,eAAO,MAAM,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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Flex } from '../flex/Flex.js';
|
|
2
2
|
import { NumberStepper } from '../number-stepper/NumberStepper.js';
|
|
3
|
-
import React__default, {
|
|
3
|
+
import React__default, { useRef } from 'react';
|
|
4
4
|
import { ActiveFilterInstance } from './ActiveFilterInstance.js';
|
|
5
5
|
import { resolveOperators } from './resolveOperators.js';
|
|
6
|
-
import { isEmptyValue } from './utils.js';
|
|
7
6
|
|
|
8
7
|
const GTE = {
|
|
9
8
|
inputType: { type: "number" },
|
|
@@ -31,43 +30,62 @@ function numberFilter({ excludes, includes, ...config }) {
|
|
|
31
30
|
}
|
|
32
31
|
class NumberActiveFilter extends ActiveFilterInstance {
|
|
33
32
|
formatValue() {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
: String(this.value);
|
|
33
|
+
return [this.value]
|
|
34
|
+
.flat()
|
|
35
|
+
.filter((value) => value !== undefined)
|
|
36
|
+
.join(" and ");
|
|
39
37
|
}
|
|
40
38
|
renderEditor(onChange) {
|
|
41
|
-
const { label } = this.operator;
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
: [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
const { inputType, label, name } = this.operator;
|
|
40
|
+
const [start, end] = [this.value].flat();
|
|
41
|
+
const { initialValues, labels, toValue } = inputType.type === "number-range"
|
|
42
|
+
? {
|
|
43
|
+
initialValues: [start, end],
|
|
44
|
+
labels: [`${label} from`, `${label} to`],
|
|
45
|
+
toValue: (committed) => committed,
|
|
46
|
+
}
|
|
47
|
+
: {
|
|
48
|
+
initialValues: [start],
|
|
49
|
+
labels: [label],
|
|
50
|
+
toValue: (committed) => committed[0],
|
|
51
|
+
};
|
|
52
|
+
return (React__default.createElement(NumberEditor, { key: name, labels: labels, values: initialValues, onCommit: (committed) => onChange({ value: toValue(committed) }, { complete: committed.every((value) => value !== undefined) }) }));
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
// React Aria parses typed text in its own blur and Enter handlers, after ours,
|
|
56
|
+
// so parsed values go in a ref and commit from the wrapper's blur (which
|
|
57
|
+
// bubbles after parsing) or Enter's keyup.
|
|
58
|
+
function NumberEditor({ labels, onCommit, values: initialValues, }) {
|
|
59
|
+
const values = useRef(initialValues);
|
|
60
|
+
const lastCommitted = useRef(initialValues);
|
|
61
|
+
const shouldCommitOnKeyUp = useRef(false);
|
|
62
|
+
const commit = () => {
|
|
63
|
+
lastCommitted.current = values.current;
|
|
64
|
+
onCommit(values.current);
|
|
65
|
+
};
|
|
66
|
+
const changed = () => values.current.some((value, index) => value !== lastCommitted.current[index]);
|
|
67
|
+
return (React__default.createElement(Flex, { gap: 1, onBlur: () => {
|
|
68
|
+
if (changed())
|
|
69
|
+
commit();
|
|
70
|
+
} }, labels.map((label, index) => (React__default.createElement(React__default.Fragment, { key: label },
|
|
71
|
+
index > 0 && React__default.createElement("span", null, "and"),
|
|
64
72
|
React__default.createElement(NumberStepper
|
|
65
73
|
// eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices
|
|
66
74
|
, {
|
|
67
75
|
// eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices
|
|
68
|
-
autoFocus:
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
autoFocus: index === 0, defaultValue: initialValues[index], hideLabel: true, label: label, onChange: (value) => {
|
|
77
|
+
const next = [...values.current];
|
|
78
|
+
next[index] = Number.isNaN(value) ? undefined : value;
|
|
79
|
+
values.current = next;
|
|
80
|
+
}, onKeyDown: (e) => {
|
|
81
|
+
shouldCommitOnKeyUp.current =
|
|
82
|
+
e.key === "Enter" && !e.nativeEvent.isComposing;
|
|
83
|
+
}, onKeyUp: (e) => {
|
|
84
|
+
if (e.key !== "Enter" || !shouldCommitOnKeyUp.current)
|
|
85
|
+
return;
|
|
86
|
+
shouldCommitOnKeyUp.current = false;
|
|
87
|
+
commit();
|
|
88
|
+
} }))))));
|
|
71
89
|
}
|
|
72
90
|
|
|
73
91
|
export { GTE, LTE, NUMBER_RANGE, numberFilter };
|
|
@@ -1 +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, {
|
|
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, { useRef } from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\n\nexport type NumberFilterValue = number | [number, number]\n\nexport const GTE = {\n inputType: { type: \"number\" },\n label: \">=\",\n name: \"gte\",\n} as const satisfies Operator\nexport const 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 [this.value]\n .flat()\n .filter((value) => value !== undefined)\n .join(\" and \")\n }\n\n renderEditor(onChange: FilterChange) {\n const { inputType, label, name } = this.operator\n const [start, end] = [this.value].flat()\n const { initialValues, labels, toValue } =\n inputType.type === \"number-range\"\n ? {\n initialValues: [start, end],\n labels: [`${label} from`, `${label} to`],\n toValue: (committed: NumberInputValue[]) => committed,\n }\n : {\n initialValues: [start],\n labels: [label],\n toValue: (committed: NumberInputValue[]) => committed[0],\n }\n return (\n <NumberEditor\n key={name}\n labels={labels}\n values={initialValues}\n onCommit={(committed) =>\n onChange(\n { value: toValue(committed) },\n { complete: committed.every((value) => value !== undefined) }\n )\n }\n />\n )\n }\n}\n\ntype NumberInputValue = number | undefined\n\n// React Aria parses typed text in its own blur and Enter handlers, after ours,\n// so parsed values go in a ref and commit from the wrapper's blur (which\n// bubbles after parsing) or Enter's keyup.\nfunction NumberEditor({\n labels,\n onCommit,\n values: initialValues,\n}: {\n labels: string[]\n onCommit: (values: NumberInputValue[]) => void\n values: NumberInputValue[]\n}) {\n const values = useRef(initialValues)\n const lastCommitted = useRef(initialValues)\n const shouldCommitOnKeyUp = useRef(false)\n const commit = () => {\n lastCommitted.current = values.current\n onCommit(values.current)\n }\n const changed = () =>\n values.current.some(\n (value, index) => value !== lastCommitted.current[index]\n )\n return (\n <Flex\n gap={1}\n onBlur={() => {\n if (changed()) commit()\n }}\n >\n {labels.map((label, index) => (\n <React.Fragment key={label}>\n {index > 0 && <span>and</span>}\n <NumberStepper\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus={index === 0}\n defaultValue={initialValues[index]}\n hideLabel\n label={label}\n onChange={(value) => {\n const next = [...values.current]\n next[index] = Number.isNaN(value) ? undefined : value\n values.current = next\n }}\n onKeyDown={(e) => {\n shouldCommitOnKeyUp.current =\n e.key === \"Enter\" && !e.nativeEvent.isComposing\n }}\n onKeyUp={(e) => {\n if (e.key !== \"Enter\" || !shouldCommitOnKeyUp.current) return\n shouldCommitOnKeyUp.current = false\n commit()\n }}\n />\n </React.Fragment>\n ))}\n </Flex>\n )\n}\n"],"names":["React"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Input } from '../input/Input.js';
|
|
2
|
-
import React__default, { useState } from 'react';
|
|
2
|
+
import React__default, { useState, useRef } from 'react';
|
|
3
3
|
import { ActiveFilterInstance } from './ActiveFilterInstance.js';
|
|
4
4
|
import { resolveOperators } from './resolveOperators.js';
|
|
5
5
|
import { isEmptyValue } from './utils.js';
|
|
@@ -43,11 +43,23 @@ class TextActiveFilter extends ActiveFilterInstance {
|
|
|
43
43
|
}
|
|
44
44
|
function TextEditor({ label, onCommit, value: initialValue, }) {
|
|
45
45
|
const [value, setValue] = useState(initialValue);
|
|
46
|
+
const lastCommitted = useRef(initialValue);
|
|
47
|
+
const commit = () => {
|
|
48
|
+
lastCommitted.current = value;
|
|
49
|
+
onCommit(value);
|
|
50
|
+
};
|
|
46
51
|
return (React__default.createElement(Input
|
|
47
52
|
// eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices
|
|
48
53
|
, {
|
|
49
54
|
// eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices
|
|
50
|
-
autoFocus: true, hideLabel: true, label: label, value: value, onChange: (e) => setValue(e.target.value), onBlur: () =>
|
|
55
|
+
autoFocus: true, hideLabel: true, label: label, value: value, onChange: (e) => setValue(e.target.value), onBlur: () => {
|
|
56
|
+
if (value !== lastCommitted.current)
|
|
57
|
+
commit();
|
|
58
|
+
}, onKeyDown: (e) => {
|
|
59
|
+
if (e.key === "Enter" && !e.repeat && !e.nativeEvent.isComposing) {
|
|
60
|
+
commit();
|
|
61
|
+
}
|
|
62
|
+
} }));
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
export { CONTAINS, EQ, NOT, STARTS_WITH, textFilter };
|
|
@@ -1 +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 FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\nimport { isEmptyValue } from \"./utils\"\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(onChange: FilterChange) {\n return (\n <TextEditor\n label={this.operator.label}\n value={this.value}\n onCommit={(value) =>\n onChange({ value }, { complete: !isEmptyValue(value) })\n }\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 // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus\n hideLabel\n label={label}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onBlur={() =>
|
|
1
|
+
{"version":3,"file":"textFilter.js","sources":["../../../src/components/DataTable/textFilter.tsx"],"sourcesContent":["import { Input } from \"@components/input\"\nimport React, { useRef, useState } from \"react\"\n\nimport { ActiveFilterInstance } from \"./ActiveFilterInstance\"\nimport type {\n FilterChange,\n FilterItemConfig,\n FilterNodeItem,\n Operator,\n} from \"./FilterTypes\"\nimport { resolveOperators } from \"./resolveOperators\"\nimport { isEmptyValue } from \"./utils\"\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(onChange: FilterChange) {\n return (\n <TextEditor\n label={this.operator.label}\n value={this.value}\n onCommit={(value) =>\n onChange({ value }, { complete: !isEmptyValue(value) })\n }\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 const lastCommitted = useRef(initialValue)\n const commit = () => {\n lastCommitted.current = value\n onCommit(value)\n }\n return (\n <Input\n // eslint-disable-next-line jsx-a11y/no-autofocus -- the editor only ever renders inside a chip popover that just opened, per ARIA dialog practices\n autoFocus\n hideLabel\n label={label}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onBlur={() => {\n if (value !== lastCommitted.current) commit()\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.repeat && !e.nativeEvent.isComposing) {\n commit()\n }\n }}\n />\n )\n}\n"],"names":["React"],"mappings":";;;;;;AAaO,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,QAAsB,EAAA;AACjC,QAAA,QACEA,cAAA,CAAA,aAAA,CAAC,UAAU,IACT,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAC1B,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,QAAQ,EAAE,CAAC,KAAK,KACd,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAA,CAEzD;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,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAK;AAClB,QAAA,aAAa,CAAC,OAAO,GAAG,KAAK;QAC7B,QAAQ,CAAC,KAAK,CAAC;AACjB,IAAA,CAAC;IACD,QACEA,6BAAC;;;;AAEC,QAAA,SAAS,EAAA,IAAA,EACT,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,MAAK;AACX,YAAA,IAAI,KAAK,KAAK,aAAa,CAAC,OAAO;AAAE,gBAAA,MAAM,EAAE;AAC/C,QAAA,CAAC,EACD,SAAS,EAAE,CAAC,CAAC,KAAI;AACf,YAAA,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE;AAChE,gBAAA,MAAM,EAAE;YACV;QACF,CAAC,EAAA,CACD;AAEN;;;;"}
|