@lattice-php/lattice 0.20.0 → 0.22.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/README.md +10 -0
- package/dist/action/components/action-form.d.ts +6 -1
- package/dist/action/components/action-form.js +48 -58
- package/dist/action/components/action-form.js.map +1 -1
- package/dist/action/components/action-trigger-provider.d.ts +1 -1
- package/dist/action/components/action-trigger-provider.js.map +1 -1
- package/dist/action/components/action.js +2 -1
- package/dist/action/components/action.js.map +1 -1
- package/dist/action/hooks/use-action.d.ts +1 -1
- package/dist/action/hooks/use-action.js +42 -33
- package/dist/action/hooks/use-action.js.map +1 -1
- package/dist/action/index.d.ts +0 -2
- package/dist/action/index.js +1 -2
- package/dist/action/lib/action-label.d.ts +2 -0
- package/dist/action/lib/action-label.js +9 -0
- package/dist/action/lib/action-label.js.map +1 -0
- package/dist/action/lib/run-action.d.ts +7 -7
- package/dist/action/lib/run-action.js +8 -7
- package/dist/action/lib/run-action.js.map +1 -1
- package/dist/chat/plugin.d.ts +0 -1
- package/dist/chat/plugin.js.map +1 -1
- package/dist/clipboard/index.d.ts +0 -4
- package/dist/clipboard/index.js +1 -15
- package/dist/{events → core}/event-names.js +1 -1
- package/dist/core/event-names.js.map +1 -0
- package/dist/core/hooks/use-window-event.d.ts +8 -0
- package/dist/core/hooks/use-window-event.js +22 -0
- package/dist/core/hooks/use-window-event.js.map +1 -0
- package/dist/core/index.js +3 -3
- package/dist/core/types.d.ts +8 -73
- package/dist/create-app.js +1 -1
- package/dist/effects/dispatch.js +1 -1
- package/dist/effects/dispatch.js.map +1 -1
- package/dist/effects/registry.d.ts +2 -18
- package/dist/effects/registry.js +4 -8
- package/dist/effects/registry.js.map +1 -1
- package/dist/event-bridge.js +10 -23
- package/dist/event-bridge.js.map +1 -1
- package/dist/form/components/fields/date-picker-field.js +1 -1
- package/dist/form/components/fields/file-upload.js +4 -6
- package/dist/form/components/fields/file-upload.js.map +1 -1
- package/dist/form/components/fields/select.js +2 -2
- package/dist/form/components/fields/select.js.map +1 -1
- package/dist/form/components/fields/table-rows.js +3 -15
- package/dist/form/components/fields/table-rows.js.map +1 -1
- package/dist/form/components/form.js +11 -24
- package/dist/form/components/form.js.map +1 -1
- package/dist/form/embed.d.ts +4 -0
- package/dist/form/embed.js +3 -1
- package/dist/form/lib/collect-fields.d.ts +7 -0
- package/dist/form/lib/collect-fields.js +19 -0
- package/dist/form/lib/collect-fields.js.map +1 -0
- package/dist/form/lib/field-errors.d.ts +3 -0
- package/dist/form/lib/field-errors.js +11 -0
- package/dist/form/lib/field-errors.js.map +1 -0
- package/dist/format/format-context.d.ts +6 -0
- package/dist/format/format-context.js +17 -0
- package/dist/format/format-context.js.map +1 -0
- package/dist/format/number.d.ts +1 -1
- package/dist/format/number.js.map +1 -1
- package/dist/format/value.d.ts +1 -1
- package/dist/format/value.js.map +1 -1
- package/dist/i18n/backend.js +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/instance.js +1 -1
- package/dist/i18n/locale-reload.d.ts +1 -1
- package/dist/i18n/locale-reload.js +7 -6
- package/dist/i18n/locale-reload.js.map +1 -1
- package/dist/i18n/locale.js +1 -1
- package/dist/i18n/locale.js.map +1 -1
- package/dist/i18n/page-props.js +1 -1
- package/dist/i18n/shared-props.js +1 -3
- package/dist/i18n/shared-props.js.map +1 -1
- package/dist/i18n/timezone.js +1 -1
- package/dist/i18n/timezone.js.map +1 -1
- package/dist/index.d.ts +6 -7
- package/dist/index.js +7 -8
- package/dist/lattice.css +105 -0
- package/dist/layout/components/callouts.js +1 -1
- package/dist/layout/components/sidebar.js +15 -48
- package/dist/layout/components/sidebar.js.map +1 -1
- package/dist/layout/plugin.d.ts +0 -1
- package/dist/layout/plugin.js.map +1 -1
- package/dist/lib/is-truthy.d.ts +2 -0
- package/dist/lib/is-truthy.js +9 -0
- package/dist/lib/is-truthy.js.map +1 -0
- package/dist/lib/use-debounced-callback.d.ts +10 -0
- package/dist/lib/use-debounced-callback.js +34 -0
- package/dist/lib/use-debounced-callback.js.map +1 -0
- package/dist/lib/use-media-query.d.ts +5 -0
- package/dist/lib/use-media-query.js +26 -0
- package/dist/lib/use-media-query.js.map +1 -0
- package/dist/lib/use-persistent-state.d.ts +13 -0
- package/dist/lib/use-persistent-state.js +62 -0
- package/dist/lib/use-persistent-state.js.map +1 -0
- package/dist/notifications/components/notifications.js +4 -1
- package/dist/notifications/components/notifications.js.map +1 -1
- package/dist/notifications/plugin.d.ts +0 -1
- package/dist/notifications/plugin.js.map +1 -1
- package/dist/provider-base.js +1 -1
- package/dist/realtime/listeners.d.ts +1 -1
- package/dist/realtime/listeners.js +1 -1
- package/dist/realtime/listeners.js.map +1 -1
- package/dist/registry.d.ts +5 -0
- package/dist/registry.js.map +1 -1
- package/dist/remote/components/data-list.js +1 -1
- package/dist/remote/plugin.d.ts +0 -1
- package/dist/remote/plugin.js.map +1 -1
- package/dist/table/components/bulk-bar.js +18 -15
- package/dist/table/components/bulk-bar.js.map +1 -1
- package/dist/table/components/cells/boolean-cell.js +1 -3
- package/dist/table/components/cells/boolean-cell.js.map +1 -1
- package/dist/table/components/cells/copyable-cell.d.ts +9 -0
- package/dist/table/components/cells/copyable-cell.js +17 -0
- package/dist/table/components/cells/copyable-cell.js.map +1 -0
- package/dist/table/components/cells/money-cell.js +7 -18
- package/dist/table/components/cells/money-cell.js.map +1 -1
- package/dist/table/components/cells/number-cell.js +14 -27
- package/dist/table/components/cells/number-cell.js.map +1 -1
- package/dist/table/components/cells/numeric-cell.d.ts +10 -0
- package/dist/table/components/cells/numeric-cell.js +25 -0
- package/dist/table/components/cells/numeric-cell.js.map +1 -0
- package/dist/table/components/cells/stack-cell.js +1 -1
- package/dist/table/components/cells/text-cell.js +4 -5
- package/dist/table/components/cells/text-cell.js.map +1 -1
- package/dist/table/components/filter-controls.js +1 -3
- package/dist/table/components/filter-controls.js.map +1 -1
- package/dist/table/components/table-cell.js.map +1 -1
- package/dist/table/components/table-search.js +4 -7
- package/dist/table/components/table-search.js.map +1 -1
- package/dist/table/components/table.js +2 -3
- package/dist/table/components/table.js.map +1 -1
- package/dist/table/hooks/use-column-visibility.js +29 -58
- package/dist/table/hooks/use-column-visibility.js.map +1 -1
- package/dist/table/hooks/use-table.js +5 -13
- package/dist/table/hooks/use-table.js.map +1 -1
- package/dist/table/lib/bulk.d.ts +2 -0
- package/dist/table/lib/bulk.js +5 -2
- package/dist/table/lib/bulk.js.map +1 -1
- package/dist/table/lib/query.js +1 -1
- package/dist/table/lib/query.js.map +1 -1
- package/dist/table/plugin.d.ts +0 -1
- package/dist/table/plugin.js.map +1 -1
- package/dist/table/types.d.ts +4 -57
- package/dist/toast/callout.js +1 -1
- package/dist/toast/callout.js.map +1 -1
- package/dist/toast/index.d.ts +1 -1
- package/dist/toast/index.js +2 -2
- package/dist/toast/toast.d.ts +0 -2
- package/dist/toast/toast.js +3 -10
- package/dist/toast/toast.js.map +1 -1
- package/dist/toast/toaster.js +2 -2
- package/dist/types/generated.d.ts +224 -80
- package/dist/types/index.d.ts +1 -1
- package/dist/ui/button.d.ts +2 -2
- package/dist/ui/chart-view.js +7 -30
- package/dist/ui/chart-view.js.map +1 -1
- package/dist/ui/click-behavior.d.ts +4 -4
- package/dist/ui/click-behavior.js.map +1 -1
- package/dist/ui/collapsible.js +3 -15
- package/dist/ui/collapsible.js.map +1 -1
- package/dist/ui/combobox.js +6 -3
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/confirm-dialog.js +1 -1
- package/dist/ui/confirm-dialog.js.map +1 -1
- package/dist/ui/control.d.ts +1 -1
- package/dist/ui/dialog.d.ts +6 -2
- package/dist/ui/dialog.js +29 -5
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/fragment.js +1 -1
- package/dist/ui/fragment.js.map +1 -1
- package/dist/ui/icon-button.d.ts +1 -1
- package/dist/ui/image-preview.js +1 -1
- package/dist/ui/image-preview.js.map +1 -1
- package/dist/ui/modal.js +6 -3
- package/dist/ui/modal.js.map +1 -1
- package/dist/ui/pill.d.ts +2 -0
- package/dist/ui/pill.js +10 -0
- package/dist/ui/pill.js.map +1 -0
- package/dist/ui/plugin.js.map +1 -1
- package/dist/ui/progress.js +1 -1
- package/dist/ui/section.js +2 -15
- package/dist/ui/section.js.map +1 -1
- package/dist/ui/segmented-pills.js +2 -1
- package/dist/ui/segmented-pills.js.map +1 -1
- package/dist/ui/tabs.js +12 -10
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/tree-context.js +11 -13
- package/dist/ui/tree-context.js.map +1 -1
- package/dist/ui/tree.js +1 -1
- package/dist/ui/tree.js.map +1 -1
- package/dist/ui/use-collapsible-state.d.ts +7 -0
- package/dist/ui/use-collapsible-state.js +21 -0
- package/dist/ui/use-collapsible-state.js.map +1 -0
- package/dist-standalone/chunks/chart-view-C6R5iPra.js +36 -0
- package/dist-standalone/chunks/{date-picker-field-VbH9xrQO.js → date-picker-field-DhhEB-Mh.js} +1 -1
- package/dist-standalone/chunks/{page-props-AIa5UR6n.js → page-props-DOfg30l5.js} +1 -1
- package/dist-standalone/chunks/{rich-editor-field-DLQTyt36.js → rich-editor-field-DORXTHPw.js} +2 -2
- package/dist-standalone/chunks/{subscriptions-DY2tj9Im.js → subscriptions-DK_s_F2g.js} +1 -1
- package/dist-standalone/chunks/use-effect-dispatcher-EVZxmfoo.js +97 -0
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +15 -15
- package/dist-standalone/manifest.json +8 -8
- package/package.json +3 -3
- package/dist/clipboard/index.js.map +0 -1
- package/dist/events/event-names.js.map +0 -1
- package/dist/table/components/table-action-node.d.ts +0 -4
- package/dist/table/components/table-action-node.js +0 -24
- package/dist/table/components/table-action-node.js.map +0 -1
- package/dist-standalone/chunks/chart-view-wJmnVu7L.js +0 -36
- package/dist-standalone/chunks/use-effect-dispatcher-feEs0GCP.js +0 -97
- /package/dist/{events → core}/event-names.d.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from "../../lib/utils.js";
|
|
2
2
|
import { Icon } from "../../icons/sprite.js";
|
|
3
|
-
import { Renderer } from "../../core/renderer.js";
|
|
3
|
+
import { RenderNode, Renderer } from "../../core/renderer.js";
|
|
4
4
|
import { useT } from "../../i18n/instance.js";
|
|
5
5
|
import { nodeIdentity } from "../../core/test-id.js";
|
|
6
6
|
import { useColumnResizing } from "../../core/hooks/use-column-resizing.js";
|
|
@@ -21,7 +21,6 @@ import { FilterBar, FilterMenu } from "./filter-bar.js";
|
|
|
21
21
|
import { TablePagination } from "./pagination.js";
|
|
22
22
|
import { SortBar } from "./sort-bar.js";
|
|
23
23
|
import { TableSearch } from "./table-search.js";
|
|
24
|
-
import { TableActionNode } from "./table-action-node.js";
|
|
25
24
|
import { ColumnCell } from "./table-cell.js";
|
|
26
25
|
import { Fragment, useMemo } from "react";
|
|
27
26
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -296,7 +295,7 @@ var TableComponent = ({ node }) => {
|
|
|
296
295
|
hasTrailingUtility && /* @__PURE__ */ jsx("div", {
|
|
297
296
|
className: cn("items-center justify-start gap-2 px-lt-cell-x py-lt-cell-y md:justify-end", actions.length > 0 ? "flex" : "hidden md:flex"),
|
|
298
297
|
role: "cell",
|
|
299
|
-
children: actions.map((action, actionIndex) => /* @__PURE__ */ jsx(
|
|
298
|
+
children: actions.map((action, actionIndex) => /* @__PURE__ */ jsx(RenderNode, { node: action }, action.key ?? action.id ?? actionIndex))
|
|
300
299
|
})
|
|
301
300
|
]
|
|
302
301
|
}), expanded && detail && /* @__PURE__ */ jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.js","names":[],"sources":["../../../resources/js/table/components/table.tsx"],"sourcesContent":["import { type ReactNode, Fragment, useMemo } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport { useColumnResizing } from \"@lattice-php/lattice/core/hooks/use-column-resizing\";\nimport { useColumnVisibility } from \"@lattice-php/lattice/table/hooks/use-column-visibility\";\nimport { useExpandedRows } from \"@lattice-php/lattice/table/hooks/use-expanded-rows\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { alignJustifyItems, alignText } from \"@lattice-php/lattice/table/lib/align\";\nimport type { TableNode } from \"@lattice-php/lattice/table/types\";\nimport { getBulkActions } from \"@lattice-php/lattice/table/lib/bulk\";\nimport { getRowActions, getRowDetail, getRowKey } from \"@lattice-php/lattice/table/lib/payload\";\nimport {\n getQueryParams,\n getTableSizingColumns,\n getTableUtilityTracks,\n getVisiblePages,\n} from \"@lattice-php/lattice/table/lib/query\";\nimport { useTable } from \"@lattice-php/lattice/table/hooks/use-table\";\nimport { useTableSelection } from \"@lattice-php/lattice/table/hooks/use-table-selection\";\nimport { BulkBar } from \"./bulk-bar\";\nimport { ColumnFilterControl } from \"./column-filter-control\";\nimport { ColumnHeader } from \"./column-header\";\nimport { ColumnVisibilityMenu } from \"./column-visibility-menu\";\nimport { FilterBar, FilterMenu } from \"./filter-bar\";\nimport { TablePagination } from \"./pagination\";\nimport { SortBar } from \"./sort-bar\";\nimport { TableSearch } from \"./table-search\";\nimport { TableActionNode } from \"./table-action-node\";\nimport { ColumnCell } from \"./table-cell\";\n\nconst TableComponent = ({ node }: { children?: ReactNode; node: TableNode }) => {\n const { t } = useT(\"lattice\");\n const {\n columns,\n rows,\n pagination,\n query,\n filters,\n tableFilters,\n search,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n setSearch,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n } = useTable(node);\n\n const bulkActions = useMemo(\n () => getBulkActions(node.props?.bulkActions),\n [node.props?.bulkActions],\n );\n const hasBulkActions = bulkActions.length > 0;\n const rowEntries = useMemo(\n () =>\n rows.map((row, index) => ({\n row,\n actions: getRowActions(row),\n detail: getRowDetail(row),\n key: getRowKey(row, index),\n })),\n [rows],\n );\n const selection = useTableSelection(rowEntries.map((entry) => entry.key));\n const { isExpanded, toggle: toggleRow } = useExpandedRows();\n const hasExpandable = rowEntries.some((entry) => entry.detail != null);\n\n const columnsByKey = useMemo(\n () => new Map(columns.map((column) => [column.key, column])),\n [columns],\n );\n const visibilityIdentity = nodeIdentity(node);\n const {\n hasToggleableColumns,\n hasHidden,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n } = useColumnVisibility({\n columns,\n storageKey: visibilityIdentity\n ? `lattice:table-column-visibility:${visibilityIdentity}`\n : undefined,\n });\n const currentPage = pagination.currentPage ?? query.page;\n const lastPage = pagination.lastPage ?? currentPage;\n const mode = pagination.mode ?? \"table\";\n const visiblePages = getVisiblePages(currentPage, lastPage);\n const hasNextPage = pagination.hasMore ?? currentPage < lastPage;\n const hasActions = rowEntries.some((entry) => entry.actions.length > 0);\n const striped = node.props?.striped === true;\n const hasFilters = visibleColumns.some((column) => column.props.filter != null);\n const filterEntries = filters.map((clause, index) => ({ clause, index }));\n const filterDefinitions = useMemo(\n () => (Array.isArray(node.props?.filters) ? node.props.filters : []),\n [node.props?.filters],\n );\n const hasDedicatedFilters = filterDefinitions.length > 0;\n const hasTrailingUtility = hasActions || hasDedicatedFilters || hasToggleableColumns;\n const sizingColumns = useMemo(() => getTableSizingColumns(visibleColumns), [visibleColumns]);\n const utilityTracks = useMemo(\n () => getTableUtilityTracks(hasTrailingUtility, hasBulkActions, hasExpandable),\n [hasTrailingUtility, hasBulkActions, hasExpandable],\n );\n const resizingEnabled = node.props?.resizableColumns === true;\n const resizeStorageIdentity = nodeIdentity(node);\n const { getResizeHandleProps, gridTemplateColumns, hasOverrides, resizeRootRef, resetColumns } =\n useColumnResizing({\n columns: sizingColumns,\n enabled: resizingEnabled,\n leadingTracks: utilityTracks.leadingTracks,\n showIndicator: node.props?.resizeIndicator === true,\n storageKey:\n resizingEnabled && resizeStorageIdentity\n ? `lattice:table-columns:${resizeStorageIdentity}`\n : undefined,\n trailingTracks: utilityTracks.trailingTracks,\n });\n\n return (\n <div data-slot=\"table\" data-lattice-component={node.id} className=\"relative\">\n {hasOverrides && (\n <button\n aria-label={t(\"table.reset-column-widths\", \"Reset column widths\")}\n className=\"absolute right-1 top-1 z-10 hidden rounded-lt-sm p-1 text-lt-muted-fg hover:text-lt-fg md:inline-flex\"\n data-test=\"table-reset-columns\"\n onClick={resetColumns}\n title={t(\"table.reset-column-widths\", \"Reset column widths\")}\n type=\"button\"\n >\n <Icon name=\"rotate-ccw\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n <div\n data-slot=\"table-scroll\"\n className=\"overflow-x-auto rounded-lt-sm border border-lt-border\"\n >\n {node.props?.searchable && (\n <div\n data-slot=\"table-toolbar\"\n className=\"flex items-center gap-2 border-b border-lt-border px-4 py-2\"\n >\n <TableSearch value={search} onSearch={setSearch} />\n </div>\n )}\n <FilterBar\n clauses={filters}\n columnsByKey={columnsByKey}\n indicators={query.tableFilterIndicators}\n processing={processing}\n onRemoveClause={removeFilter}\n onChange={setTableFilter}\n onReset={resetFilters}\n />\n {hasBulkActions && selection.active && (\n <BulkBar\n actions={bulkActions}\n selectedKeys={selection.selectedKeys}\n allMatching={selection.allMatching}\n total={pagination.total ?? undefined}\n query={getQueryParams(query)}\n canSelectAllMatching={\n selection.allVisibleSelected &&\n !selection.allMatching &&\n pagination.total != null &&\n pagination.total > selection.selectedKeys.length\n }\n onSelectAllMatching={selection.selectAllMatching}\n onCompleted={selection.clear}\n />\n )}\n {query.sorts.length > 0 && (\n <SortBar\n columnsByKey={columnsByKey}\n query={query}\n processing={processing}\n onClear={clearSort}\n />\n )}\n <div\n ref={resizeRootRef}\n className=\"min-w-full text-base\"\n role=\"table\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n <div\n data-slot=\"table-header\"\n className=\"border-b border-lt-border bg-lt-muted/50\"\n role=\"rowgroup\"\n >\n <div\n className=\"hidden min-w-full md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n >\n {hasExpandable && (\n <div className=\"px-2 py-3\" role=\"columnheader\" aria-hidden=\"true\" />\n )}\n {hasBulkActions && (\n <div className=\"flex items-center px-4 py-3\" role=\"columnheader\">\n <Checkbox\n aria-label={t(\"table.select-all-rows\", \"Select all rows\")}\n data-test=\"select-all\"\n checked={selection.allSelected}\n onCheckedChange={() => selection.toggleAll()}\n />\n </div>\n )}\n {visibleColumns.map((column, index) => (\n <ColumnHeader\n column={column}\n key={column.key}\n processing={processing}\n resizeHandleProps={\n resizingEnabled ? getResizeHandleProps(sizingColumns[index]) : undefined\n }\n sort={sort}\n query={query}\n />\n ))}\n {hasTrailingUtility && (\n <div\n className=\"flex items-center justify-end gap-2 px-4 py-2 align-middle font-semibold text-lt-fg\"\n role=\"columnheader\"\n >\n {hasDedicatedFilters && (\n <FilterMenu\n filters={filterDefinitions}\n values={tableFilters}\n processing={processing}\n onChange={setTableFilter}\n onSearch={searchFilterOptions}\n />\n )}\n {hasToggleableColumns && (\n <ColumnVisibilityMenu\n columns={toggleableColumns}\n isVisible={isVisible}\n visibleColumnCount={visibleColumns.length}\n hasHidden={hasHidden}\n onToggle={setColumnVisible}\n onReset={resetVisibility}\n processing={processing}\n />\n )}\n {hasActions && (\n <span className=\"sr-only\">\n {node.props?.actionsLabel ?? t(\"table.actions\", \"Actions\")}\n </span>\n )}\n </div>\n )}\n </div>\n {hasFilters && (\n <div\n className=\"hidden min-w-full border-t border-lt-border md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n >\n {hasExpandable && <div className=\"px-2 py-2\" role=\"cell\" />}\n {hasBulkActions && <div className=\"px-4 py-2\" role=\"cell\" />}\n {visibleColumns.map((column) => (\n <div key={column.key} className=\"min-w-0 px-2 py-2\" role=\"cell\">\n {column.props.filter != null && (\n <ColumnFilterControl\n column={column}\n clauses={filterEntries.filter((entry) => entry.clause.field === column.key)}\n processing={processing}\n onAdd={addFilter}\n onUpdate={updateFilter}\n onRemove={removeFilter}\n onReplace={replaceColumnFilters}\n onSearch={(query, signal) =>\n searchFilterOptions(`column:${column.key}`, query, signal)\n }\n />\n )}\n </div>\n ))}\n {hasTrailingUtility && <div className=\"px-4 py-2\" role=\"cell\" />}\n </div>\n )}\n </div>\n <div role=\"rowgroup\">\n {!hasLoaded ? (\n <div className=\"p-4 text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{t(\"table.loading\", \"Loading rows...\")}</div>\n </div>\n ) : rowEntries.length === 0 ? (\n <div data-slot=\"table-empty\" className=\"p-8 text-center text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{node.props?.emptyLabel ?? t(\"table.empty\", \"No results\")}</div>\n </div>\n ) : (\n rowEntries.map(({ row, actions, detail, key }) => {\n const expanded = detail != null && isExpanded(key);\n const detailId = `${nodeIdentity(node) ?? \"table\"}-row-detail-${key}`;\n\n return (\n <Fragment key={key}>\n <div\n data-slot=\"table-row\"\n className={`grid grid-cols-1 border-b border-lt-border last:border-b-0 md:grid-cols-[var(--lattice-table-columns)] ${\n striped ? \"odd:bg-lt-muted/30\" : \"\"\n }`}\n role=\"row\"\n >\n {hasExpandable && (\n <div className=\"flex items-center px-2 py-lt-cell-y\" role=\"cell\">\n {detail && (\n <button\n type=\"button\"\n data-test={`row-expand-${key}`}\n aria-expanded={expanded}\n aria-controls={detailId}\n aria-label={t(\"table.row-detail.toggle\", \"Toggle detail\")}\n className=\"inline-flex size-6 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted hover:text-lt-fg\"\n onClick={() => toggleRow(key)}\n >\n <Icon\n name=\"chevron-down\"\n aria-hidden=\"true\"\n className={cn(\n \"size-lt-icon-md transition-transform\",\n !expanded && \"-rotate-90\",\n )}\n />\n </button>\n )}\n </div>\n )}\n {hasBulkActions && (\n <div className=\"flex items-center px-lt-cell-x py-lt-cell-y\" role=\"cell\">\n <Checkbox\n aria-label={t(\"table.select-row\", \"Select row {{key}}\", { key })}\n data-test={`select-row-${key}`}\n checked={selection.isSelected(key)}\n onCheckedChange={() => selection.toggle(key)}\n />\n </div>\n )}\n {visibleColumns.map((column) => (\n <div\n key={column.key}\n data-slot=\"table-cell\"\n className={cn(\n \"grid min-w-0 gap-1 overflow-hidden px-lt-cell-x py-lt-cell-y align-middle\",\n alignText(column.props.align),\n alignJustifyItems(column.props.align),\n )}\n role=\"cell\"\n >\n <span\n aria-hidden=\"true\"\n className=\"text-xs font-medium text-lt-muted-fg md:hidden\"\n >\n {column.props.label}\n </span>\n <div\n data-slot=\"table-cell-content\"\n className=\"min-w-0 max-w-full overflow-hidden truncate\"\n >\n <ColumnCell column={column} row={row} />\n </div>\n </div>\n ))}\n {hasTrailingUtility && (\n <div\n className={cn(\n \"items-center justify-start gap-2 px-lt-cell-x py-lt-cell-y md:justify-end\",\n actions.length > 0 ? \"flex\" : \"hidden md:flex\",\n )}\n role=\"cell\"\n >\n {actions.map((action, actionIndex) => (\n <TableActionNode\n key={action.key ?? action.id ?? actionIndex}\n node={action}\n />\n ))}\n </div>\n )}\n </div>\n {expanded && detail && (\n <div\n id={detailId}\n role=\"region\"\n data-slot=\"table-row-detail\"\n className=\"border-b border-lt-border bg-lt-muted/20 px-lt-cell-x py-lt-cell-y\"\n >\n <Renderer nodes={[detail]} />\n </div>\n )}\n </Fragment>\n );\n })\n )}\n </div>\n </div>\n {hasLoaded && (\n <TablePagination\n pagination={pagination}\n currentPage={currentPage}\n processing={processing}\n mode={mode}\n hasNextPage={hasNextPage}\n visiblePages={visiblePages}\n infiniteLoaderRef={infiniteLoaderRef}\n onPage={goToPage}\n onLoadMore={loadMore}\n />\n )}\n </div>\n </div>\n );\n};\n\nexport default TableComponent;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table.js","names":[],"sources":["../../../resources/js/table/components/table.tsx"],"sourcesContent":["import { type ReactNode, Fragment, useMemo } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Renderer, RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport { useColumnResizing } from \"@lattice-php/lattice/core/hooks/use-column-resizing\";\nimport { useColumnVisibility } from \"@lattice-php/lattice/table/hooks/use-column-visibility\";\nimport { useExpandedRows } from \"@lattice-php/lattice/table/hooks/use-expanded-rows\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { alignJustifyItems, alignText } from \"@lattice-php/lattice/table/lib/align\";\nimport type { TableNode } from \"@lattice-php/lattice/table/types\";\nimport { getBulkActions } from \"@lattice-php/lattice/table/lib/bulk\";\nimport { getRowActions, getRowDetail, getRowKey } from \"@lattice-php/lattice/table/lib/payload\";\nimport {\n getQueryParams,\n getTableSizingColumns,\n getTableUtilityTracks,\n getVisiblePages,\n} from \"@lattice-php/lattice/table/lib/query\";\nimport { useTable } from \"@lattice-php/lattice/table/hooks/use-table\";\nimport { useTableSelection } from \"@lattice-php/lattice/table/hooks/use-table-selection\";\nimport { BulkBar } from \"./bulk-bar\";\nimport { ColumnFilterControl } from \"./column-filter-control\";\nimport { ColumnHeader } from \"./column-header\";\nimport { ColumnVisibilityMenu } from \"./column-visibility-menu\";\nimport { FilterBar, FilterMenu } from \"./filter-bar\";\nimport { TablePagination } from \"./pagination\";\nimport { SortBar } from \"./sort-bar\";\nimport { TableSearch } from \"./table-search\";\nimport { ColumnCell } from \"./table-cell\";\n\nconst TableComponent = ({ node }: { children?: ReactNode; node: TableNode }) => {\n const { t } = useT(\"lattice\");\n const {\n columns,\n rows,\n pagination,\n query,\n filters,\n tableFilters,\n search,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n setSearch,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n } = useTable(node);\n\n const bulkActions = useMemo(\n () => getBulkActions(node.props?.bulkActions),\n [node.props?.bulkActions],\n );\n const hasBulkActions = bulkActions.length > 0;\n const rowEntries = useMemo(\n () =>\n rows.map((row, index) => ({\n row,\n actions: getRowActions(row),\n detail: getRowDetail(row),\n key: getRowKey(row, index),\n })),\n [rows],\n );\n const selection = useTableSelection(rowEntries.map((entry) => entry.key));\n const { isExpanded, toggle: toggleRow } = useExpandedRows();\n const hasExpandable = rowEntries.some((entry) => entry.detail != null);\n\n const columnsByKey = useMemo(\n () => new Map(columns.map((column) => [column.key, column])),\n [columns],\n );\n const visibilityIdentity = nodeIdentity(node);\n const {\n hasToggleableColumns,\n hasHidden,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n } = useColumnVisibility({\n columns,\n storageKey: visibilityIdentity\n ? `lattice:table-column-visibility:${visibilityIdentity}`\n : undefined,\n });\n const currentPage = pagination.currentPage ?? query.page;\n const lastPage = pagination.lastPage ?? currentPage;\n const mode = pagination.mode ?? \"table\";\n const visiblePages = getVisiblePages(currentPage, lastPage);\n const hasNextPage = pagination.hasMore ?? currentPage < lastPage;\n const hasActions = rowEntries.some((entry) => entry.actions.length > 0);\n const striped = node.props?.striped === true;\n const hasFilters = visibleColumns.some((column) => column.props.filter != null);\n const filterEntries = filters.map((clause, index) => ({ clause, index }));\n const filterDefinitions = useMemo(\n () => (Array.isArray(node.props?.filters) ? node.props.filters : []),\n [node.props?.filters],\n );\n const hasDedicatedFilters = filterDefinitions.length > 0;\n const hasTrailingUtility = hasActions || hasDedicatedFilters || hasToggleableColumns;\n const sizingColumns = useMemo(() => getTableSizingColumns(visibleColumns), [visibleColumns]);\n const utilityTracks = useMemo(\n () => getTableUtilityTracks(hasTrailingUtility, hasBulkActions, hasExpandable),\n [hasTrailingUtility, hasBulkActions, hasExpandable],\n );\n const resizingEnabled = node.props?.resizableColumns === true;\n const resizeStorageIdentity = nodeIdentity(node);\n const { getResizeHandleProps, gridTemplateColumns, hasOverrides, resizeRootRef, resetColumns } =\n useColumnResizing({\n columns: sizingColumns,\n enabled: resizingEnabled,\n leadingTracks: utilityTracks.leadingTracks,\n showIndicator: node.props?.resizeIndicator === true,\n storageKey:\n resizingEnabled && resizeStorageIdentity\n ? `lattice:table-columns:${resizeStorageIdentity}`\n : undefined,\n trailingTracks: utilityTracks.trailingTracks,\n });\n\n return (\n <div data-slot=\"table\" data-lattice-component={node.id} className=\"relative\">\n {hasOverrides && (\n <button\n aria-label={t(\"table.reset-column-widths\", \"Reset column widths\")}\n className=\"absolute right-1 top-1 z-10 hidden rounded-lt-sm p-1 text-lt-muted-fg hover:text-lt-fg md:inline-flex\"\n data-test=\"table-reset-columns\"\n onClick={resetColumns}\n title={t(\"table.reset-column-widths\", \"Reset column widths\")}\n type=\"button\"\n >\n <Icon name=\"rotate-ccw\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n <div\n data-slot=\"table-scroll\"\n className=\"overflow-x-auto rounded-lt-sm border border-lt-border\"\n >\n {node.props?.searchable && (\n <div\n data-slot=\"table-toolbar\"\n className=\"flex items-center gap-2 border-b border-lt-border px-4 py-2\"\n >\n <TableSearch value={search} onSearch={setSearch} />\n </div>\n )}\n <FilterBar\n clauses={filters}\n columnsByKey={columnsByKey}\n indicators={query.tableFilterIndicators}\n processing={processing}\n onRemoveClause={removeFilter}\n onChange={setTableFilter}\n onReset={resetFilters}\n />\n {hasBulkActions && selection.active && (\n <BulkBar\n actions={bulkActions}\n selectedKeys={selection.selectedKeys}\n allMatching={selection.allMatching}\n total={pagination.total ?? undefined}\n query={getQueryParams(query)}\n canSelectAllMatching={\n selection.allVisibleSelected &&\n !selection.allMatching &&\n pagination.total != null &&\n pagination.total > selection.selectedKeys.length\n }\n onSelectAllMatching={selection.selectAllMatching}\n onCompleted={selection.clear}\n />\n )}\n {query.sorts.length > 0 && (\n <SortBar\n columnsByKey={columnsByKey}\n query={query}\n processing={processing}\n onClear={clearSort}\n />\n )}\n <div\n ref={resizeRootRef}\n className=\"min-w-full text-base\"\n role=\"table\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n <div\n data-slot=\"table-header\"\n className=\"border-b border-lt-border bg-lt-muted/50\"\n role=\"rowgroup\"\n >\n <div\n className=\"hidden min-w-full md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n >\n {hasExpandable && (\n <div className=\"px-2 py-3\" role=\"columnheader\" aria-hidden=\"true\" />\n )}\n {hasBulkActions && (\n <div className=\"flex items-center px-4 py-3\" role=\"columnheader\">\n <Checkbox\n aria-label={t(\"table.select-all-rows\", \"Select all rows\")}\n data-test=\"select-all\"\n checked={selection.allSelected}\n onCheckedChange={() => selection.toggleAll()}\n />\n </div>\n )}\n {visibleColumns.map((column, index) => (\n <ColumnHeader\n column={column}\n key={column.key}\n processing={processing}\n resizeHandleProps={\n resizingEnabled ? getResizeHandleProps(sizingColumns[index]) : undefined\n }\n sort={sort}\n query={query}\n />\n ))}\n {hasTrailingUtility && (\n <div\n className=\"flex items-center justify-end gap-2 px-4 py-2 align-middle font-semibold text-lt-fg\"\n role=\"columnheader\"\n >\n {hasDedicatedFilters && (\n <FilterMenu\n filters={filterDefinitions}\n values={tableFilters}\n processing={processing}\n onChange={setTableFilter}\n onSearch={searchFilterOptions}\n />\n )}\n {hasToggleableColumns && (\n <ColumnVisibilityMenu\n columns={toggleableColumns}\n isVisible={isVisible}\n visibleColumnCount={visibleColumns.length}\n hasHidden={hasHidden}\n onToggle={setColumnVisible}\n onReset={resetVisibility}\n processing={processing}\n />\n )}\n {hasActions && (\n <span className=\"sr-only\">\n {node.props?.actionsLabel ?? t(\"table.actions\", \"Actions\")}\n </span>\n )}\n </div>\n )}\n </div>\n {hasFilters && (\n <div\n className=\"hidden min-w-full border-t border-lt-border md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n >\n {hasExpandable && <div className=\"px-2 py-2\" role=\"cell\" />}\n {hasBulkActions && <div className=\"px-4 py-2\" role=\"cell\" />}\n {visibleColumns.map((column) => (\n <div key={column.key} className=\"min-w-0 px-2 py-2\" role=\"cell\">\n {column.props.filter != null && (\n <ColumnFilterControl\n column={column}\n clauses={filterEntries.filter((entry) => entry.clause.field === column.key)}\n processing={processing}\n onAdd={addFilter}\n onUpdate={updateFilter}\n onRemove={removeFilter}\n onReplace={replaceColumnFilters}\n onSearch={(query, signal) =>\n searchFilterOptions(`column:${column.key}`, query, signal)\n }\n />\n )}\n </div>\n ))}\n {hasTrailingUtility && <div className=\"px-4 py-2\" role=\"cell\" />}\n </div>\n )}\n </div>\n <div role=\"rowgroup\">\n {!hasLoaded ? (\n <div className=\"p-4 text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{t(\"table.loading\", \"Loading rows...\")}</div>\n </div>\n ) : rowEntries.length === 0 ? (\n <div data-slot=\"table-empty\" className=\"p-8 text-center text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{node.props?.emptyLabel ?? t(\"table.empty\", \"No results\")}</div>\n </div>\n ) : (\n rowEntries.map(({ row, actions, detail, key }) => {\n const expanded = detail != null && isExpanded(key);\n const detailId = `${nodeIdentity(node) ?? \"table\"}-row-detail-${key}`;\n\n return (\n <Fragment key={key}>\n <div\n data-slot=\"table-row\"\n className={`grid grid-cols-1 border-b border-lt-border last:border-b-0 md:grid-cols-[var(--lattice-table-columns)] ${\n striped ? \"odd:bg-lt-muted/30\" : \"\"\n }`}\n role=\"row\"\n >\n {hasExpandable && (\n <div className=\"flex items-center px-2 py-lt-cell-y\" role=\"cell\">\n {detail && (\n <button\n type=\"button\"\n data-test={`row-expand-${key}`}\n aria-expanded={expanded}\n aria-controls={detailId}\n aria-label={t(\"table.row-detail.toggle\", \"Toggle detail\")}\n className=\"inline-flex size-6 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted hover:text-lt-fg\"\n onClick={() => toggleRow(key)}\n >\n <Icon\n name=\"chevron-down\"\n aria-hidden=\"true\"\n className={cn(\n \"size-lt-icon-md transition-transform\",\n !expanded && \"-rotate-90\",\n )}\n />\n </button>\n )}\n </div>\n )}\n {hasBulkActions && (\n <div className=\"flex items-center px-lt-cell-x py-lt-cell-y\" role=\"cell\">\n <Checkbox\n aria-label={t(\"table.select-row\", \"Select row {{key}}\", { key })}\n data-test={`select-row-${key}`}\n checked={selection.isSelected(key)}\n onCheckedChange={() => selection.toggle(key)}\n />\n </div>\n )}\n {visibleColumns.map((column) => (\n <div\n key={column.key}\n data-slot=\"table-cell\"\n className={cn(\n \"grid min-w-0 gap-1 overflow-hidden px-lt-cell-x py-lt-cell-y align-middle\",\n alignText(column.props.align),\n alignJustifyItems(column.props.align),\n )}\n role=\"cell\"\n >\n <span\n aria-hidden=\"true\"\n className=\"text-xs font-medium text-lt-muted-fg md:hidden\"\n >\n {column.props.label}\n </span>\n <div\n data-slot=\"table-cell-content\"\n className=\"min-w-0 max-w-full overflow-hidden truncate\"\n >\n <ColumnCell column={column} row={row} />\n </div>\n </div>\n ))}\n {hasTrailingUtility && (\n <div\n className={cn(\n \"items-center justify-start gap-2 px-lt-cell-x py-lt-cell-y md:justify-end\",\n actions.length > 0 ? \"flex\" : \"hidden md:flex\",\n )}\n role=\"cell\"\n >\n {actions.map((action, actionIndex) => (\n <RenderNode\n key={action.key ?? action.id ?? actionIndex}\n node={action}\n />\n ))}\n </div>\n )}\n </div>\n {expanded && detail && (\n <div\n id={detailId}\n role=\"region\"\n data-slot=\"table-row-detail\"\n className=\"border-b border-lt-border bg-lt-muted/20 px-lt-cell-x py-lt-cell-y\"\n >\n <Renderer nodes={[detail]} />\n </div>\n )}\n </Fragment>\n );\n })\n )}\n </div>\n </div>\n {hasLoaded && (\n <TablePagination\n pagination={pagination}\n currentPage={currentPage}\n processing={processing}\n mode={mode}\n hasNextPage={hasNextPage}\n visiblePages={visiblePages}\n infiniteLoaderRef={infiniteLoaderRef}\n onPage={goToPage}\n onLoadMore={loadMore}\n />\n )}\n </div>\n </div>\n );\n};\n\nexport default TableComponent;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,kBAAkB,EAAE,WAAsD;CAC9E,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,EACJ,SACA,MACA,YACA,OACA,SACA,cACA,QACA,WACA,cACA,cACA,sBACA,gBACA,cACA,WACA,qBACA,YACA,WACA,mBACA,MACA,WACA,UACA,aACE,SAAS,IAAI;CAEjB,MAAM,cAAc,cACZ,eAAe,KAAK,OAAO,WAAW,GAC5C,CAAC,KAAK,OAAO,WAAW,CAC1B;CACA,MAAM,iBAAiB,YAAY,SAAS;CAC5C,MAAM,aAAa,cAEf,KAAK,KAAK,KAAK,WAAW;EACxB;EACA,SAAS,cAAc,GAAG;EAC1B,QAAQ,aAAa,GAAG;EACxB,KAAK,UAAU,KAAK,KAAK;CAC3B,EAAE,GACJ,CAAC,IAAI,CACP;CACA,MAAM,YAAY,kBAAkB,WAAW,KAAK,UAAU,MAAM,GAAG,CAAC;CACxE,MAAM,EAAE,YAAY,QAAQ,cAAc,gBAAgB;CAC1D,MAAM,gBAAgB,WAAW,MAAM,UAAU,MAAM,UAAU,IAAI;CAErE,MAAM,eAAe,cACb,IAAI,IAAI,QAAQ,KAAK,WAAW,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,GAC3D,CAAC,OAAO,CACV;CACA,MAAM,qBAAqB,aAAa,IAAI;CAC5C,MAAM,EACJ,sBACA,WACA,WACA,iBACA,kBACA,mBACA,mBACE,oBAAoB;EACtB;EACA,YAAY,qBACR,mCAAmC,uBACnC,KAAA;CACN,CAAC;CACD,MAAM,cAAc,WAAW,eAAe,MAAM;CACpD,MAAM,WAAW,WAAW,YAAY;CACxC,MAAM,OAAO,WAAW,QAAQ;CAChC,MAAM,eAAe,gBAAgB,aAAa,QAAQ;CAC1D,MAAM,cAAc,WAAW,WAAW,cAAc;CACxD,MAAM,aAAa,WAAW,MAAM,UAAU,MAAM,QAAQ,SAAS,CAAC;CACtE,MAAM,UAAU,KAAK,OAAO,YAAY;CACxC,MAAM,aAAa,eAAe,MAAM,WAAW,OAAO,MAAM,UAAU,IAAI;CAC9E,MAAM,gBAAgB,QAAQ,KAAK,QAAQ,WAAW;EAAE;EAAQ;CAAM,EAAE;CACxE,MAAM,oBAAoB,cACjB,MAAM,QAAQ,KAAK,OAAO,OAAO,IAAI,KAAK,MAAM,UAAU,CAAC,GAClE,CAAC,KAAK,OAAO,OAAO,CACtB;CACA,MAAM,sBAAsB,kBAAkB,SAAS;CACvD,MAAM,qBAAqB,cAAc,uBAAuB;CAChE,MAAM,gBAAgB,cAAc,sBAAsB,cAAc,GAAG,CAAC,cAAc,CAAC;CAC3F,MAAM,gBAAgB,cACd,sBAAsB,oBAAoB,gBAAgB,aAAa,GAC7E;EAAC;EAAoB;EAAgB;CAAa,CACpD;CACA,MAAM,kBAAkB,KAAK,OAAO,qBAAqB;CACzD,MAAM,wBAAwB,aAAa,IAAI;CAC/C,MAAM,EAAE,sBAAsB,qBAAqB,cAAc,eAAe,iBAC9E,kBAAkB;EAChB,SAAS;EACT,SAAS;EACT,eAAe,cAAc;EAC7B,eAAe,KAAK,OAAO,oBAAoB;EAC/C,YACE,mBAAmB,wBACf,yBAAyB,0BACzB,KAAA;EACN,gBAAgB,cAAc;CAChC,CAAC;CAEH,OACE,qBAAC,OAAD;EAAK,aAAU;EAAQ,0BAAwB,KAAK;EAAI,WAAU;YAAlE,CACG,gBACC,oBAAC,UAAD;GACE,cAAY,EAAE,6BAA6B,qBAAqB;GAChE,WAAU;GACV,aAAU;GACV,SAAS;GACT,OAAO,EAAE,6BAA6B,qBAAqB;GAC3D,MAAK;aAEL,oBAAC,MAAD;IAAM,MAAK;IAAa,WAAU;GAAmB,CAAA;EAC/C,CAAA,GAEV,qBAAC,OAAD;GACE,aAAU;GACV,WAAU;aAFZ;IAIG,KAAK,OAAO,cACX,oBAAC,OAAD;KACE,aAAU;KACV,WAAU;eAEV,oBAAC,aAAD;MAAa,OAAO;MAAQ,UAAU;KAAY,CAAA;IAC/C,CAAA;IAEP,oBAAC,WAAD;KACE,SAAS;KACK;KACd,YAAY,MAAM;KACN;KACZ,gBAAgB;KAChB,UAAU;KACV,SAAS;IACV,CAAA;IACA,kBAAkB,UAAU,UAC3B,oBAAC,SAAD;KACE,SAAS;KACT,cAAc,UAAU;KACxB,aAAa,UAAU;KACvB,OAAO,WAAW,SAAS,KAAA;KAC3B,OAAO,eAAe,KAAK;KAC3B,sBACE,UAAU,sBACV,CAAC,UAAU,eACX,WAAW,SAAS,QACpB,WAAW,QAAQ,UAAU,aAAa;KAE5C,qBAAqB,UAAU;KAC/B,aAAa,UAAU;IACxB,CAAA;IAEF,MAAM,MAAM,SAAS,KACpB,oBAAC,SAAD;KACgB;KACP;KACK;KACZ,SAAS;IACV,CAAA;IAEH,qBAAC,OAAD;KACE,KAAK;KACL,WAAU;KACV,MAAK;KACL,OAAO,EAAE,2BAA2B,oBAAoB;eAJ1D,CAME,qBAAC,OAAD;MACE,aAAU;MACV,WAAU;MACV,MAAK;gBAHP,CAKE,qBAAC,OAAD;OACE,WAAU;OACV,MAAK;iBAFP;QAIG,iBACC,oBAAC,OAAD;SAAK,WAAU;SAAY,MAAK;SAAe,eAAY;QAAQ,CAAA;QAEpE,kBACC,oBAAC,OAAD;SAAK,WAAU;SAA8B,MAAK;mBAChD,oBAAC,UAAD;UACE,cAAY,EAAE,yBAAyB,iBAAiB;UACxD,aAAU;UACV,SAAS,UAAU;UACnB,uBAAuB,UAAU,UAAU;SAC5C,CAAA;QACE,CAAA;QAEN,eAAe,KAAK,QAAQ,UAC3B,oBAAC,cAAD;SACU;SAEI;SACZ,mBACE,kBAAkB,qBAAqB,cAAc,MAAM,IAAI,KAAA;SAE3D;SACC;QACR,GAPM,OAAO,GAOb,CACF;QACA,sBACC,qBAAC,OAAD;SACE,WAAU;SACV,MAAK;mBAFP;UAIG,uBACC,oBAAC,YAAD;WACE,SAAS;WACT,QAAQ;WACI;WACZ,UAAU;WACV,UAAU;UACX,CAAA;UAEF,wBACC,oBAAC,sBAAD;WACE,SAAS;WACE;WACX,oBAAoB,eAAe;WACxB;WACX,UAAU;WACV,SAAS;WACG;UACb,CAAA;UAEF,cACC,oBAAC,QAAD;WAAM,WAAU;qBACb,KAAK,OAAO,gBAAgB,EAAE,iBAAiB,SAAS;UACrD,CAAA;SAEL;;OAEJ;UACJ,cACC,qBAAC,OAAD;OACE,WAAU;OACV,MAAK;iBAFP;QAIG,iBAAiB,oBAAC,OAAD;SAAK,WAAU;SAAY,MAAK;QAAQ,CAAA;QACzD,kBAAkB,oBAAC,OAAD;SAAK,WAAU;SAAY,MAAK;QAAQ,CAAA;QAC1D,eAAe,KAAK,WACnB,oBAAC,OAAD;SAAsB,WAAU;SAAoB,MAAK;mBACtD,OAAO,MAAM,UAAU,QACtB,oBAAC,qBAAD;UACU;UACR,SAAS,cAAc,QAAQ,UAAU,MAAM,OAAO,UAAU,OAAO,GAAG;UAC9D;UACZ,OAAO;UACP,UAAU;UACV,UAAU;UACV,WAAW;UACX,WAAW,OAAO,WAChB,oBAAoB,UAAU,OAAO,OAAO,OAAO,MAAM;SAE5D,CAAA;QAEA,GAfK,OAAO,GAeZ,CACN;QACA,sBAAsB,oBAAC,OAAD;SAAK,WAAU;SAAY,MAAK;QAAQ,CAAA;OAC5D;QAEJ;SACL,oBAAC,OAAD;MAAK,MAAK;gBACP,CAAC,YACA,oBAAC,OAAD;OAAK,WAAU;OAAuB,MAAK;iBACzC,oBAAC,OAAD;QAAK,MAAK;kBAAQ,EAAE,iBAAiB,iBAAiB;OAAO,CAAA;MAC1D,CAAA,IACH,WAAW,WAAW,IACxB,oBAAC,OAAD;OAAK,aAAU;OAAc,WAAU;OAAmC,MAAK;iBAC7E,oBAAC,OAAD;QAAK,MAAK;kBAAQ,KAAK,OAAO,cAAc,EAAE,eAAe,YAAY;OAAO,CAAA;MAC7E,CAAA,IAEL,WAAW,KAAK,EAAE,KAAK,SAAS,QAAQ,UAAU;OAChD,MAAM,WAAW,UAAU,QAAQ,WAAW,GAAG;OACjD,MAAM,WAAW,GAAG,aAAa,IAAI,KAAK,QAAQ,cAAc;OAEhE,OACE,qBAAC,UAAD,EAAA,UAAA,CACE,qBAAC,OAAD;QACE,aAAU;QACV,WAAW,0GACT,UAAU,uBAAuB;QAEnC,MAAK;kBALP;SAOG,iBACC,oBAAC,OAAD;UAAK,WAAU;UAAsC,MAAK;oBACvD,UACC,oBAAC,UAAD;WACE,MAAK;WACL,aAAW,cAAc;WACzB,iBAAe;WACf,iBAAe;WACf,cAAY,EAAE,2BAA2B,eAAe;WACxD,WAAU;WACV,eAAe,UAAU,GAAG;qBAE5B,oBAAC,MAAD;YACE,MAAK;YACL,eAAY;YACZ,WAAW,GACT,wCACA,CAAC,YAAY,YACf;WACD,CAAA;UACK,CAAA;SAEP,CAAA;SAEN,kBACC,oBAAC,OAAD;UAAK,WAAU;UAA8C,MAAK;oBAChE,oBAAC,UAAD;WACE,cAAY,EAAE,oBAAoB,sBAAsB,EAAE,IAAI,CAAC;WAC/D,aAAW,cAAc;WACzB,SAAS,UAAU,WAAW,GAAG;WACjC,uBAAuB,UAAU,OAAO,GAAG;UAC5C,CAAA;SACE,CAAA;SAEN,eAAe,KAAK,WACnB,qBAAC,OAAD;UAEE,aAAU;UACV,WAAW,GACT,6EACA,UAAU,OAAO,MAAM,KAAK,GAC5B,kBAAkB,OAAO,MAAM,KAAK,CACtC;UACA,MAAK;oBARP,CAUE,oBAAC,QAAD;WACE,eAAY;WACZ,WAAU;qBAET,OAAO,MAAM;UACV,CAAA,GACN,oBAAC,OAAD;WACE,aAAU;WACV,WAAU;qBAEV,oBAAC,YAAD;YAAoB;YAAa;WAAM,CAAA;UACpC,CAAA,CACF;YArBE,OAAO,GAqBT,CACN;SACA,sBACC,oBAAC,OAAD;UACE,WAAW,GACT,6EACA,QAAQ,SAAS,IAAI,SAAS,gBAChC;UACA,MAAK;oBAEJ,QAAQ,KAAK,QAAQ,gBACpB,oBAAC,YAAD,EAEE,MAAM,OACP,GAFM,OAAO,OAAO,OAAO,MAAM,WAEjC,CACF;SACE,CAAA;QAEJ;WACJ,YAAY,UACX,oBAAC,OAAD;QACE,IAAI;QACJ,MAAK;QACL,aAAU;QACV,WAAU;kBAEV,oBAAC,UAAD,EAAU,OAAO,CAAC,MAAM,EAAI,CAAA;OACzB,CAAA,CAEC,EAAA,GA9FK,GA8FL;MAEd,CAAC;KAEA,CAAA,CACF;;IACJ,aACC,oBAAC,iBAAD;KACc;KACC;KACD;KACN;KACO;KACC;KACK;KACnB,QAAQ;KACR,YAAY;IACb,CAAA;GAEA;IACF;;AAET"}
|
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { usePersistentState } from "../../lib/use-persistent-state.js";
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
2
3
|
//#region resources/js/table/hooks/use-column-visibility.ts
|
|
3
4
|
function useColumnVisibility({ columns, storageKey }) {
|
|
4
5
|
const toggleableColumns = useMemo(() => columns.filter((column) => column.props.toggleable), [columns]);
|
|
5
6
|
const toggleableKeys = useMemo(() => toggleableColumns.map((column) => column.key), [toggleableColumns]);
|
|
6
|
-
const [overrides, setOverrides] =
|
|
7
|
+
const [overrides, setOverrides] = usePersistentState(storageKey ?? "", {}, {
|
|
8
|
+
enabled: Boolean(storageKey),
|
|
9
|
+
parse: (raw) => parseStoredVisibility(raw, toggleableKeys),
|
|
10
|
+
serialize: (value) => serializeVisibility(value, toggleableKeys)
|
|
11
|
+
});
|
|
7
12
|
const isVisible = useCallback((column) => {
|
|
8
13
|
if (!column.props.toggleable) return true;
|
|
9
14
|
return overrides[column.key] ?? !column.props.hiddenByDefault;
|
|
10
15
|
}, [overrides]);
|
|
11
16
|
const visibleColumns = useMemo(() => columns.filter((column) => isVisible(column)), [columns, isVisible]);
|
|
12
17
|
const setColumnVisible = useCallback((key, visible) => {
|
|
13
|
-
setOverrides((current) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return next;
|
|
20
|
-
});
|
|
21
|
-
}, [storageKey, toggleableKeys]);
|
|
22
|
-
const resetVisibility = useCallback(() => {
|
|
23
|
-
setOverrides({});
|
|
24
|
-
writeStoredVisibility(storageKey, toggleableKeys, {});
|
|
25
|
-
}, [storageKey, toggleableKeys]);
|
|
18
|
+
setOverrides((current) => ({
|
|
19
|
+
...current,
|
|
20
|
+
[key]: visible
|
|
21
|
+
}));
|
|
22
|
+
}, [setOverrides]);
|
|
23
|
+
const resetVisibility = useCallback(() => setOverrides({}), [setOverrides]);
|
|
26
24
|
const hasToggleableColumns = toggleableColumns.length > 0;
|
|
27
25
|
return {
|
|
28
26
|
hasHidden: toggleableColumns.some((column) => !isVisible(column)),
|
|
@@ -34,51 +32,24 @@ function useColumnVisibility({ columns, storageKey }) {
|
|
|
34
32
|
visibleColumns
|
|
35
33
|
};
|
|
36
34
|
}
|
|
37
|
-
function
|
|
38
|
-
if (!storageKey || typeof window === "undefined") return {};
|
|
39
|
-
try {
|
|
40
|
-
const raw = window.localStorage.getItem(storageKey);
|
|
41
|
-
if (raw === null) return {};
|
|
42
|
-
const stored = JSON.parse(raw);
|
|
43
|
-
if (!isStoredColumnVisibility(stored)) {
|
|
44
|
-
removeStoredVisibility(storageKey);
|
|
45
|
-
return {};
|
|
46
|
-
}
|
|
47
|
-
const known = new Set(toggleableKeys);
|
|
48
|
-
const overrides = {};
|
|
49
|
-
for (const [key, value] of Object.entries(stored.overrides)) if (known.has(key) && typeof value === "boolean") overrides[key] = value;
|
|
50
|
-
if (Object.keys(overrides).length === 0) removeStoredVisibility(storageKey);
|
|
51
|
-
return overrides;
|
|
52
|
-
} catch {
|
|
53
|
-
removeStoredVisibility(storageKey);
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function writeStoredVisibility(storageKey, toggleableKeys, overrides) {
|
|
58
|
-
if (!storageKey || typeof window === "undefined") return;
|
|
35
|
+
function pickKnownBooleans(source, toggleableKeys) {
|
|
59
36
|
const known = new Set(toggleableKeys);
|
|
60
|
-
const
|
|
61
|
-
for (const [key, value] of Object.entries(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
columns: toggleableKeys,
|
|
69
|
-
overrides: stored
|
|
70
|
-
}));
|
|
71
|
-
} catch {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const [key, value] of Object.entries(source)) if (known.has(key) && typeof value === "boolean") result[key] = value;
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
function parseStoredVisibility(raw, toggleableKeys) {
|
|
42
|
+
const stored = JSON.parse(raw);
|
|
43
|
+
if (!isStoredColumnVisibility(stored)) throw new Error("unexpected stored column visibility shape");
|
|
44
|
+
return pickKnownBooleans(stored.overrides, toggleableKeys);
|
|
74
45
|
}
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
46
|
+
function serializeVisibility(overrides, toggleableKeys) {
|
|
47
|
+
const stored = pickKnownBooleans(overrides, toggleableKeys);
|
|
48
|
+
if (Object.keys(stored).length === 0) return null;
|
|
49
|
+
return JSON.stringify({
|
|
50
|
+
columns: toggleableKeys,
|
|
51
|
+
overrides: stored
|
|
52
|
+
});
|
|
82
53
|
}
|
|
83
54
|
function isStoredColumnVisibility(value) {
|
|
84
55
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-column-visibility.js","names":[],"sources":["../../../resources/js/table/hooks/use-column-visibility.ts"],"sourcesContent":["import { useCallback, useMemo
|
|
1
|
+
{"version":3,"file":"use-column-visibility.js","names":[],"sources":["../../../resources/js/table/hooks/use-column-visibility.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { usePersistentState } from \"@lattice-php/lattice/lib/use-persistent-state\";\n\nexport type ToggleableColumn = {\n key: string;\n props: {\n label?: string | null;\n toggleable?: boolean;\n hiddenByDefault?: boolean;\n };\n};\n\ntype StoredColumnVisibility = {\n columns: string[];\n overrides: Record<string, boolean>;\n};\n\nexport function useColumnVisibility<TColumn extends ToggleableColumn>({\n columns,\n storageKey,\n}: {\n columns: TColumn[];\n storageKey?: string;\n}) {\n const toggleableColumns = useMemo(\n () => columns.filter((column) => column.props.toggleable),\n [columns],\n );\n const toggleableKeys = useMemo(\n () => toggleableColumns.map((column) => column.key),\n [toggleableColumns],\n );\n\n const [overrides, setOverrides] = usePersistentState<Record<string, boolean>>(\n storageKey ?? \"\",\n {},\n {\n enabled: Boolean(storageKey),\n parse: (raw) => parseStoredVisibility(raw, toggleableKeys),\n serialize: (value) => serializeVisibility(value, toggleableKeys),\n },\n );\n\n const isVisible = useCallback(\n (column: ToggleableColumn): boolean => {\n if (!column.props.toggleable) {\n return true;\n }\n\n return overrides[column.key] ?? !column.props.hiddenByDefault;\n },\n [overrides],\n );\n\n const visibleColumns = useMemo(\n () => columns.filter((column) => isVisible(column)),\n [columns, isVisible],\n );\n\n const setColumnVisible = useCallback(\n (key: string, visible: boolean) => {\n setOverrides((current) => ({ ...current, [key]: visible }));\n },\n [setOverrides],\n );\n\n const resetVisibility = useCallback(() => setOverrides({}), [setOverrides]);\n\n const hasToggleableColumns = toggleableColumns.length > 0;\n const hasHidden = toggleableColumns.some((column) => !isVisible(column));\n\n return {\n hasHidden,\n hasToggleableColumns,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n };\n}\n\nfunction pickKnownBooleans(\n source: Record<string, unknown>,\n toggleableKeys: string[],\n): Record<string, boolean> {\n const known = new Set(toggleableKeys);\n const result: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(source)) {\n if (known.has(key) && typeof value === \"boolean\") {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nfunction parseStoredVisibility(raw: string, toggleableKeys: string[]): Record<string, boolean> {\n const stored = JSON.parse(raw) as unknown;\n\n if (!isStoredColumnVisibility(stored)) {\n throw new Error(\"unexpected stored column visibility shape\");\n }\n\n return pickKnownBooleans(stored.overrides, toggleableKeys);\n}\n\nfunction serializeVisibility(\n overrides: Record<string, boolean>,\n toggleableKeys: string[],\n): string | null {\n const stored = pickKnownBooleans(overrides, toggleableKeys);\n\n if (Object.keys(stored).length === 0) {\n return null;\n }\n\n return JSON.stringify({ columns: toggleableKeys, overrides: stored });\n}\n\nfunction isStoredColumnVisibility(value: unknown): value is StoredColumnVisibility {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const record = value as Record<string, unknown>;\n\n return (\n Array.isArray(record.columns) &&\n record.columns.every((column) => typeof column === \"string\") &&\n typeof record.overrides === \"object\" &&\n record.overrides !== null &&\n !Array.isArray(record.overrides)\n );\n}\n"],"mappings":";;;AAiBA,SAAgB,oBAAsD,EACpE,SACA,cAIC;CACD,MAAM,oBAAoB,cAClB,QAAQ,QAAQ,WAAW,OAAO,MAAM,UAAU,GACxD,CAAC,OAAO,CACV;CACA,MAAM,iBAAiB,cACf,kBAAkB,KAAK,WAAW,OAAO,GAAG,GAClD,CAAC,iBAAiB,CACpB;CAEA,MAAM,CAAC,WAAW,gBAAgB,mBAChC,cAAc,IACd,CAAC,GACD;EACE,SAAS,QAAQ,UAAU;EAC3B,QAAQ,QAAQ,sBAAsB,KAAK,cAAc;EACzD,YAAY,UAAU,oBAAoB,OAAO,cAAc;CACjE,CACF;CAEA,MAAM,YAAY,aACf,WAAsC;EACrC,IAAI,CAAC,OAAO,MAAM,YAChB,OAAO;EAGT,OAAO,UAAU,OAAO,QAAQ,CAAC,OAAO,MAAM;CAChD,GACA,CAAC,SAAS,CACZ;CAEA,MAAM,iBAAiB,cACf,QAAQ,QAAQ,WAAW,UAAU,MAAM,CAAC,GAClD,CAAC,SAAS,SAAS,CACrB;CAEA,MAAM,mBAAmB,aACtB,KAAa,YAAqB;EACjC,cAAc,aAAa;GAAE,GAAG;IAAU,MAAM;EAAQ,EAAE;CAC5D,GACA,CAAC,YAAY,CACf;CAEA,MAAM,kBAAkB,kBAAkB,aAAa,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;CAE1E,MAAM,uBAAuB,kBAAkB,SAAS;CAGxD,OAAO;EACL,WAHgB,kBAAkB,MAAM,WAAW,CAAC,UAAU,MAAM,CAGpE;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,SAAS,kBACP,QACA,gBACyB;CACzB,MAAM,QAAQ,IAAI,IAAI,cAAc;CACpC,MAAM,SAAkC,CAAC;CAEzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,MAAM,IAAI,GAAG,KAAK,OAAO,UAAU,WACrC,OAAO,OAAO;CAIlB,OAAO;AACT;AAEA,SAAS,sBAAsB,KAAa,gBAAmD;CAC7F,MAAM,SAAS,KAAK,MAAM,GAAG;CAE7B,IAAI,CAAC,yBAAyB,MAAM,GAClC,MAAM,IAAI,MAAM,2CAA2C;CAG7D,OAAO,kBAAkB,OAAO,WAAW,cAAc;AAC3D;AAEA,SAAS,oBACP,WACA,gBACe;CACf,MAAM,SAAS,kBAAkB,WAAW,cAAc;CAE1D,IAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GACjC,OAAO;CAGT,OAAO,KAAK,UAAU;EAAE,SAAS;EAAgB,WAAW;CAAO,CAAC;AACtE;AAEA,SAAS,yBAAyB,OAAiD;CACjF,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,SAAS;CAEf,OACE,MAAM,QAAQ,OAAO,OAAO,KAC5B,OAAO,QAAQ,OAAO,WAAW,OAAO,WAAW,QAAQ,KAC3D,OAAO,OAAO,cAAc,YAC5B,OAAO,cAAc,QACrB,CAAC,MAAM,QAAQ,OAAO,SAAS;AAEnC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { LATTICE_EVENT } from "../../
|
|
1
|
+
import { LATTICE_EVENT } from "../../core/event-names.js";
|
|
2
|
+
import { useWindowEvent } from "../../core/hooks/use-window-event.js";
|
|
2
3
|
import { apiFetch, apiJson } from "../../core/api.js";
|
|
3
4
|
import { getColumns, getPagination, getQuery, getRows } from "../lib/payload.js";
|
|
4
5
|
import { isEmptyFilterValue, isFilterValue } from "../lib/filter-values.js";
|
|
@@ -159,18 +160,9 @@ function useTable(node) {
|
|
|
159
160
|
load,
|
|
160
161
|
query
|
|
161
162
|
]);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
load(query);
|
|
166
|
-
}
|
|
167
|
-
window.addEventListener(LATTICE_EVENT.reloadComponent, reload);
|
|
168
|
-
return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);
|
|
169
|
-
}, [
|
|
170
|
-
load,
|
|
171
|
-
node.id,
|
|
172
|
-
query
|
|
173
|
-
]);
|
|
163
|
+
useWindowEvent(LATTICE_EVENT.reloadComponent, (event) => {
|
|
164
|
+
if (event.detail?.component === node.id) load(query);
|
|
165
|
+
});
|
|
174
166
|
useEffect(() => {
|
|
175
167
|
if (!isInfinite || !pagination.hasMore || processing || !infiniteLoaderRef.current || typeof IntersectionObserver === "undefined") return;
|
|
176
168
|
const observer = new IntersectionObserver((entries) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-table.js","names":[],"sources":["../../../resources/js/table/hooks/use-table.ts"],"sourcesContent":["import { apiFetch, apiJson } from \"@lattice-php/lattice/core/api\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/lattice/events/event-names\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyFilterValue, isFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport {\n getColumns,\n getPagination,\n getRows,\n getQuery,\n} from \"@lattice-php/lattice/table/lib/payload\";\nimport { buildEndpoint, nextSort } from \"@lattice-php/lattice/table/lib/query\";\nimport type {\n FilterClause,\n TableColumn,\n TableNode,\n TableResult,\n TableSort,\n TableQuery,\n} from \"@lattice-php/lattice/table/types\";\n\nexport function useTable(node: TableNode) {\n const columns = useMemo(() => getColumns(node.props?.columns), [node.props?.columns]);\n const endpoint = typeof node.props?.endpoint === \"string\" ? node.props.endpoint : null;\n const componentRef = typeof node.props?.ref === \"string\" ? node.props.ref : \"\";\n const isLazy = node.props?.lazy === true;\n const initialQuery = useMemo(() => getQuery(node.props?.query), [node.props?.query]);\n const initialRows = useMemo(() => getRows(node.props?.data), [node.props?.data]);\n const initialPagination = useMemo(\n () => getPagination(node.props?.pagination),\n [node.props?.pagination],\n );\n const [rows, setRows] = useState(initialRows);\n const [pagination, setPagination] = useState(initialPagination);\n const [query, setQuery] = useState(initialQuery);\n const [processing, setProcessing] = useState(isLazy);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const infiniteLoaderRef = useRef<HTMLDivElement | null>(null);\n const currentPage = pagination.currentPage ?? query.page;\n const isInfinite = (pagination.mode ?? \"table\") === \"infinite\";\n\n const load = useCallback(\n async (nextQuery: TableQuery, append = false): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<TableResult>(buildEndpoint(endpoint, nextQuery), {\n ref: componentRef,\n });\n const resultQuery = getQuery(result.query);\n const resultRows = getRows(result.data);\n\n setRows((currentRows) => (append ? [...currentRows, ...resultRows] : resultRows));\n setPagination(getPagination(result.pagination));\n setQuery(resultQuery);\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n },\n [endpoint, componentRef],\n );\n\n function sort(column: TableColumn): void {\n void load({\n ...query,\n page: 1,\n sorts: nextSort(query.sorts, column),\n });\n }\n\n function clearSort(sort: TableSort): void {\n void load({\n ...query,\n page: 1,\n sorts: query.sorts.filter((currentSort) => currentSort.key !== sort.key),\n });\n }\n\n function applyFilters(next: FilterClause[]): void {\n const nextQuery = { ...query, filters: next, page: 1 };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function addFilter(clause: FilterClause): void {\n applyFilters([...query.filters, clause]);\n }\n\n function updateFilter(index: number, clause: FilterClause): void {\n applyFilters(query.filters.map((current, position) => (position === index ? clause : current)));\n }\n\n function removeFilter(index: number): void {\n applyFilters(query.filters.filter((_, current) => current !== index));\n }\n\n function replaceColumnFilters(field: string, clauses: FilterClause[]): void {\n applyFilters([...query.filters.filter((clause) => clause.field !== field), ...clauses]);\n }\n\n function setTableFilter(key: string, value: unknown): void {\n const next = { ...query.tableFilters };\n\n if (isEmptyFilterValue(value) || !isFilterValue(value)) {\n delete next[key];\n } else {\n next[key] = value;\n }\n\n const nextQuery = {\n ...query,\n tableFilters: next,\n tableFilterIndicators: query.tableFilterIndicators.filter(\n (indicator) => indicator.filter !== key,\n ),\n page: 1,\n };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function resetFilters(): void {\n const nextQuery = {\n ...query,\n filters: [],\n tableFilters: {},\n tableFilterIndicators: [],\n search: \"\",\n page: 1,\n };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function setSearch(search: string): void {\n const nextQuery = { ...query, search, page: 1 };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n const searchFilterOptions = useCallback(\n async (searchKey: string, search: string, signal?: AbortSignal): Promise<Option[]> => {\n if (!endpoint) {\n return [];\n }\n\n const url = new URL(endpoint, window.location.origin);\n url.searchParams.set(\"_search\", searchKey);\n url.searchParams.set(\"_q\", search);\n\n const response = await apiFetch(`${url.pathname}${url.search}`, {\n ref: componentRef,\n signal,\n throwOnError: false,\n });\n\n if (!response.ok) {\n return [];\n }\n\n const result = (await response.json()) as { options?: Option[] };\n\n return result.options ?? [];\n },\n [endpoint, componentRef],\n );\n\n function goToPage(page: number): void {\n void load({\n ...query,\n page,\n });\n }\n\n const loadMore = useCallback((): void => {\n if (processing || !pagination.hasMore) {\n return;\n }\n\n void load(\n {\n ...query,\n page: pagination.nextPage ?? currentPage + 1,\n },\n true,\n );\n }, [currentPage, load, pagination.hasMore, pagination.nextPage, processing, query]);\n\n useEffect(() => {\n setRows(initialRows);\n setPagination(initialPagination);\n setQuery(initialQuery);\n setProcessing(isLazy);\n setHasLoaded(!isLazy);\n }, [initialRows, initialPagination, initialQuery, isLazy]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load(query);\n }, [hasLoaded, isLazy, load, query]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load(query);\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id, query]);\n\n useEffect(() => {\n if (\n !isInfinite ||\n !pagination.hasMore ||\n processing ||\n !infiniteLoaderRef.current ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n loadMore();\n }\n },\n {\n rootMargin: \"240px\",\n },\n );\n\n observer.observe(infiniteLoaderRef.current);\n\n return () => observer.disconnect();\n }, [isInfinite, loadMore, pagination.hasMore, processing]);\n\n return {\n columns,\n rows,\n pagination,\n query,\n filters: query.filters,\n tableFilters: query.tableFilters,\n search: query.search,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n setSearch,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-table.js","names":[],"sources":["../../../resources/js/table/hooks/use-table.ts"],"sourcesContent":["import { apiFetch, apiJson } from \"@lattice-php/lattice/core/api\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/lattice/core/event-names\";\nimport { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyFilterValue, isFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport {\n getColumns,\n getPagination,\n getRows,\n getQuery,\n} from \"@lattice-php/lattice/table/lib/payload\";\nimport { buildEndpoint, nextSort } from \"@lattice-php/lattice/table/lib/query\";\nimport type {\n FilterClause,\n TableColumn,\n TableNode,\n TableResult,\n TableSort,\n TableQuery,\n} from \"@lattice-php/lattice/table/types\";\n\nexport function useTable(node: TableNode) {\n const columns = useMemo(() => getColumns(node.props?.columns), [node.props?.columns]);\n const endpoint = typeof node.props?.endpoint === \"string\" ? node.props.endpoint : null;\n const componentRef = typeof node.props?.ref === \"string\" ? node.props.ref : \"\";\n const isLazy = node.props?.lazy === true;\n const initialQuery = useMemo(() => getQuery(node.props?.query), [node.props?.query]);\n const initialRows = useMemo(() => getRows(node.props?.data), [node.props?.data]);\n const initialPagination = useMemo(\n () => getPagination(node.props?.pagination),\n [node.props?.pagination],\n );\n const [rows, setRows] = useState(initialRows);\n const [pagination, setPagination] = useState(initialPagination);\n const [query, setQuery] = useState(initialQuery);\n const [processing, setProcessing] = useState(isLazy);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const infiniteLoaderRef = useRef<HTMLDivElement | null>(null);\n const currentPage = pagination.currentPage ?? query.page;\n const isInfinite = (pagination.mode ?? \"table\") === \"infinite\";\n\n const load = useCallback(\n async (nextQuery: TableQuery, append = false): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<TableResult>(buildEndpoint(endpoint, nextQuery), {\n ref: componentRef,\n });\n const resultQuery = getQuery(result.query);\n const resultRows = getRows(result.data);\n\n setRows((currentRows) => (append ? [...currentRows, ...resultRows] : resultRows));\n setPagination(getPagination(result.pagination));\n setQuery(resultQuery);\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n },\n [endpoint, componentRef],\n );\n\n function sort(column: TableColumn): void {\n void load({\n ...query,\n page: 1,\n sorts: nextSort(query.sorts, column),\n });\n }\n\n function clearSort(sort: TableSort): void {\n void load({\n ...query,\n page: 1,\n sorts: query.sorts.filter((currentSort) => currentSort.key !== sort.key),\n });\n }\n\n function applyFilters(next: FilterClause[]): void {\n const nextQuery = { ...query, filters: next, page: 1 };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function addFilter(clause: FilterClause): void {\n applyFilters([...query.filters, clause]);\n }\n\n function updateFilter(index: number, clause: FilterClause): void {\n applyFilters(query.filters.map((current, position) => (position === index ? clause : current)));\n }\n\n function removeFilter(index: number): void {\n applyFilters(query.filters.filter((_, current) => current !== index));\n }\n\n function replaceColumnFilters(field: string, clauses: FilterClause[]): void {\n applyFilters([...query.filters.filter((clause) => clause.field !== field), ...clauses]);\n }\n\n function setTableFilter(key: string, value: unknown): void {\n const next = { ...query.tableFilters };\n\n if (isEmptyFilterValue(value) || !isFilterValue(value)) {\n delete next[key];\n } else {\n next[key] = value;\n }\n\n const nextQuery = {\n ...query,\n tableFilters: next,\n tableFilterIndicators: query.tableFilterIndicators.filter(\n (indicator) => indicator.filter !== key,\n ),\n page: 1,\n };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function resetFilters(): void {\n const nextQuery = {\n ...query,\n filters: [],\n tableFilters: {},\n tableFilterIndicators: [],\n search: \"\",\n page: 1,\n };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function setSearch(search: string): void {\n const nextQuery = { ...query, search, page: 1 };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n const searchFilterOptions = useCallback(\n async (searchKey: string, search: string, signal?: AbortSignal): Promise<Option[]> => {\n if (!endpoint) {\n return [];\n }\n\n const url = new URL(endpoint, window.location.origin);\n url.searchParams.set(\"_search\", searchKey);\n url.searchParams.set(\"_q\", search);\n\n const response = await apiFetch(`${url.pathname}${url.search}`, {\n ref: componentRef,\n signal,\n throwOnError: false,\n });\n\n if (!response.ok) {\n return [];\n }\n\n const result = (await response.json()) as { options?: Option[] };\n\n return result.options ?? [];\n },\n [endpoint, componentRef],\n );\n\n function goToPage(page: number): void {\n void load({\n ...query,\n page,\n });\n }\n\n const loadMore = useCallback((): void => {\n if (processing || !pagination.hasMore) {\n return;\n }\n\n void load(\n {\n ...query,\n page: pagination.nextPage ?? currentPage + 1,\n },\n true,\n );\n }, [currentPage, load, pagination.hasMore, pagination.nextPage, processing, query]);\n\n useEffect(() => {\n setRows(initialRows);\n setPagination(initialPagination);\n setQuery(initialQuery);\n setProcessing(isLazy);\n setHasLoaded(!isLazy);\n }, [initialRows, initialPagination, initialQuery, isLazy]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load(query);\n }, [hasLoaded, isLazy, load, query]);\n\n useWindowEvent(LATTICE_EVENT.reloadComponent, (event) => {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component === node.id) {\n void load(query);\n }\n });\n\n useEffect(() => {\n if (\n !isInfinite ||\n !pagination.hasMore ||\n processing ||\n !infiniteLoaderRef.current ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n loadMore();\n }\n },\n {\n rootMargin: \"240px\",\n },\n );\n\n observer.observe(infiniteLoaderRef.current);\n\n return () => observer.disconnect();\n }, [isInfinite, loadMore, pagination.hasMore, processing]);\n\n return {\n columns,\n rows,\n pagination,\n query,\n filters: query.filters,\n tableFilters: query.tableFilters,\n search: query.search,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n setSearch,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n };\n}\n"],"mappings":"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"}
|
package/dist/table/lib/bulk.d.ts
CHANGED
|
@@ -11,5 +11,7 @@ export type BulkAction = {
|
|
|
11
11
|
variant: ButtonVariant;
|
|
12
12
|
confirmation: Action["confirmation"];
|
|
13
13
|
form: Node | null;
|
|
14
|
+
modalSide: Action["modalSide"];
|
|
15
|
+
modalWidth: Action["modalWidth"];
|
|
14
16
|
};
|
|
15
17
|
export declare function getBulkActions(actions: ActionNode[] | undefined): BulkAction[];
|
package/dist/table/lib/bulk.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { actionLabel } from "../../action/lib/action-label.js";
|
|
1
2
|
//#region resources/js/table/lib/bulk.ts
|
|
2
3
|
function getBulkActions(actions) {
|
|
3
4
|
return (actions ?? []).flatMap((node) => {
|
|
@@ -6,13 +7,15 @@ function getBulkActions(actions) {
|
|
|
6
7
|
if (!props.endpoint) return [];
|
|
7
8
|
return [{
|
|
8
9
|
id: node.id ?? "",
|
|
9
|
-
label:
|
|
10
|
+
label: actionLabel(node),
|
|
10
11
|
method: props.method ?? "post",
|
|
11
12
|
endpoint: props.endpoint,
|
|
12
13
|
ref: props.ref ?? "",
|
|
13
14
|
variant: props.variant ?? "default",
|
|
14
15
|
confirmation: props.confirmation,
|
|
15
|
-
form: props.form
|
|
16
|
+
form: props.form,
|
|
17
|
+
modalSide: props.modalSide,
|
|
18
|
+
modalWidth: props.modalWidth
|
|
16
19
|
}];
|
|
17
20
|
});
|
|
18
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bulk.js","names":[],"sources":["../../../resources/js/table/lib/bulk.ts"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { Action, ButtonVariant } from \"@lattice-php/lattice/types/generated\";\nimport type { ActionNode } from \"@lattice-php/lattice/table/types\";\n\nexport type BulkAction = {\n id: string;\n label: string;\n method: Method;\n endpoint: string;\n ref: string;\n variant: ButtonVariant;\n confirmation: Action[\"confirmation\"];\n form: Node | null;\n};\n\nexport function getBulkActions(actions: ActionNode[] | undefined): BulkAction[] {\n return (actions ?? []).flatMap((node): BulkAction[] => {\n if (node.type === \"action.group\") {\n return [];\n }\n\n const props = node.props;\n\n if (!props.endpoint) {\n return [];\n }\n\n return [\n {\n id: node.id ?? \"\",\n label:
|
|
1
|
+
{"version":3,"file":"bulk.js","names":[],"sources":["../../../resources/js/table/lib/bulk.ts"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { Action, ButtonVariant } from \"@lattice-php/lattice/types/generated\";\nimport type { ActionNode } from \"@lattice-php/lattice/table/types\";\nimport { actionLabel } from \"@lattice-php/lattice/action/lib/action-label\";\n\nexport type BulkAction = {\n id: string;\n label: string;\n method: Method;\n endpoint: string;\n ref: string;\n variant: ButtonVariant;\n confirmation: Action[\"confirmation\"];\n form: Node | null;\n modalSide: Action[\"modalSide\"];\n modalWidth: Action[\"modalWidth\"];\n};\n\nexport function getBulkActions(actions: ActionNode[] | undefined): BulkAction[] {\n return (actions ?? []).flatMap((node): BulkAction[] => {\n if (node.type === \"action.group\") {\n return [];\n }\n\n const props = node.props;\n\n if (!props.endpoint) {\n return [];\n }\n\n return [\n {\n id: node.id ?? \"\",\n label: actionLabel(node),\n method: props.method ?? \"post\",\n endpoint: props.endpoint,\n ref: props.ref ?? \"\",\n variant: props.variant ?? \"default\",\n confirmation: props.confirmation,\n form: props.form,\n modalSide: props.modalSide,\n modalWidth: props.modalWidth,\n },\n ];\n });\n}\n"],"mappings":";;AAmBA,SAAgB,eAAe,SAAiD;CAC9E,QAAQ,WAAW,CAAC,GAAG,SAAS,SAAuB;EACrD,IAAI,KAAK,SAAS,gBAChB,OAAO,CAAC;EAGV,MAAM,QAAQ,KAAK;EAEnB,IAAI,CAAC,MAAM,UACT,OAAO,CAAC;EAGV,OAAO,CACL;GACE,IAAI,KAAK,MAAM;GACf,OAAO,YAAY,IAAI;GACvB,QAAQ,MAAM,UAAU;GACxB,UAAU,MAAM;GAChB,KAAK,MAAM,OAAO;GAClB,SAAS,MAAM,WAAW;GAC1B,cAAc,MAAM;GACpB,MAAM,MAAM;GACZ,WAAW,MAAM;GACjB,YAAY,MAAM;EACpB,CACF;CACF,CAAC;AACH"}
|
package/dist/table/lib/query.js
CHANGED
|
@@ -125,7 +125,7 @@ function getTableSizingColumns(columns) {
|
|
|
125
125
|
}));
|
|
126
126
|
}
|
|
127
127
|
function columnWidthOrDefault(column) {
|
|
128
|
-
return column.props.width ??
|
|
128
|
+
return column.props.width ?? "md";
|
|
129
129
|
}
|
|
130
130
|
function getTableUtilityTracks(hasActions, hasSelection, hasExpander = false) {
|
|
131
131
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","names":[],"sources":["../../../resources/js/table/lib/query.ts"],"sourcesContent":["import { translate } from \"@lattice-php/lattice/i18n\";\nimport { DEFAULT_COLUMN_WIDTH } from \"@lattice-php/lattice/core/hooks/column-sizing\";\nimport type { ColumnWidth } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyMember } from \"./filter-values\";\nimport type { TableColumn, TableSort, TableQuery } from \"@lattice-php/lattice/table/types\";\n\nexport function getColumnSort(query: TableQuery, column: TableColumn): TableSort | undefined {\n return query.sorts.find((currentSort) => currentSort.key === column.key);\n}\n\nexport function getColumnAriaSort(\n sort: TableSort | undefined,\n): \"ascending\" | \"descending\" | undefined {\n if (sort?.direction === \"asc\") {\n return \"ascending\";\n }\n\n if (sort?.direction === \"desc\") {\n return \"descending\";\n }\n\n return undefined;\n}\n\nexport function buildEndpoint(endpoint: string, query: TableQuery): string {\n const url = new URL(endpoint, window.location.origin);\n\n if (query.filters.length > 0) {\n url.searchParams.set(\"filter\", serializeFilters(query));\n }\n\n if (query.sorts.length > 0) {\n url.searchParams.set(\"sort\", serializeSorts(query));\n }\n\n if (query.search !== \"\") {\n url.searchParams.set(\"q\", query.search);\n }\n\n appendTableFilters(url, query.tableFilters);\n\n url.searchParams.set(\"page\", String(query.page));\n url.searchParams.set(\"per_page\", String(query.perPage));\n\n return `${url.pathname}${url.search}`;\n}\n\nfunction appendTableFilters(url: URL, tableFilters: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(getTableFilterParams(tableFilters))) {\n appendTableFilterParam(url, `tf[${key}]`, value);\n }\n}\n\nfunction getTableFilterParams(tableFilters: Record<string, unknown>): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(tableFilters)) {\n const normalized = normalizeTableFilterValue(value);\n\n if (normalized !== undefined) {\n params[key] = normalized;\n }\n }\n\n return params;\n}\n\nfunction normalizeTableFilterValue(value: unknown): unknown | undefined {\n if (isEmptyMember(value) || Array.isArray(value) || typeof value !== \"object\") {\n return undefined;\n }\n\n const entries = Object.entries(value)\n .map(([subKey, subValue]) => [subKey, normalizeTableFilterMember(subValue)] as const)\n .filter((entry): entry is readonly [string, unknown] => entry[1] !== undefined);\n\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nfunction normalizeTableFilterMember(value: unknown): unknown | undefined {\n if (isEmptyMember(value)) {\n return undefined;\n }\n\n if (Array.isArray(value)) {\n const values = value.map(normalizeTableFilterMember).filter((item) => item !== undefined);\n\n return values.length > 0 ? values : undefined;\n }\n\n if (typeof value === \"object\") {\n if (value === null) {\n return undefined;\n }\n\n const entries = Object.entries(value)\n .map(([key, item]) => [key, normalizeTableFilterMember(item)] as const)\n .filter((entry): entry is readonly [string, unknown] => entry[1] !== undefined);\n\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n }\n\n return String(value);\n}\n\nfunction appendTableFilterParam(url: URL, key: string, value: unknown): void {\n if (Array.isArray(value)) {\n for (const item of value) {\n appendTableFilterParam(url, `${key}[]`, item);\n }\n\n return;\n }\n\n if (typeof value === \"object\" && value !== null) {\n for (const [subKey, subValue] of Object.entries(value)) {\n appendTableFilterParam(url, `${key}[${subKey}]`, subValue);\n }\n\n return;\n }\n\n url.searchParams.append(key, String(value));\n}\n\nexport function getQueryParams(query: TableQuery): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (query.filters.length > 0) {\n params.filter = serializeFilters(query);\n }\n\n if (query.sorts.length > 0) {\n params.sort = serializeSorts(query);\n }\n\n const tableFilters = getTableFilterParams(query.tableFilters);\n\n if (Object.keys(tableFilters).length > 0) {\n params.tf = tableFilters;\n }\n\n if (query.search !== \"\") {\n params.q = query.search;\n }\n\n return params;\n}\n\nfunction serializeFilters(query: TableQuery): string {\n return query.filters\n .map((clause) => `${clause.field}:${clause.operator}:${encodeURIComponent(clause.value)}`)\n .join(\",\");\n}\n\nfunction serializeSorts(query: TableQuery): string {\n return query.sorts\n .map((sort) => (sort.direction === \"desc\" ? `-${sort.key}` : sort.key))\n .join(\",\");\n}\n\nconst operatorLabels: Record<string, string> = {\n contains: \"contains\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n eq: \"equals\",\n neq: \"not equals\",\n gt: \">\",\n gte: \"≥\",\n lt: \"<\",\n lte: \"≤\",\n in: \"in\",\n not_in: \"not in\",\n before: \"before\",\n after: \"after\",\n empty: \"is empty\",\n filled: \"is not empty\",\n};\n\nexport const VALUELESS_FILTER_OPERATORS = new Set<string>([\"empty\", \"filled\"]);\n\nexport function operatorLabel(operator: string): string {\n return translate(\"lattice\", `table.operators.${operator}`, operatorLabels[operator] ?? operator);\n}\n\nexport function getSortDirectionLabel(direction: string): string {\n return direction === \"desc\" ? \"descending\" : \"ascending\";\n}\n\nexport function nextSort(sorts: TableSort[], column: TableColumn): TableSort[] {\n if (!column.props.sortable) {\n return sorts;\n }\n\n const currentSort = sorts.find((sort) => sort.key === column.key);\n const remainingSorts = sorts.filter((sort) => sort.key !== column.key);\n\n if (!currentSort) {\n return [...sorts, { key: column.key, direction: \"asc\" }];\n }\n\n if (currentSort.direction === \"asc\") {\n return [...remainingSorts, { key: column.key, direction: \"desc\" }];\n }\n\n return remainingSorts;\n}\n\nexport function getVisiblePages(currentPage: number, lastPage: number): number[] {\n if (lastPage <= 5) {\n return Array.from({ length: lastPage }, (_, index) => index + 1);\n }\n\n const start = Math.max(1, Math.min(currentPage - 2, lastPage - 4));\n\n return Array.from({ length: 5 }, (_, index) => start + index);\n}\n\nexport function getTableSizingColumns(columns: TableColumn[]) {\n return columns.map((column) => ({\n key: column.key,\n label: column.props.label,\n width: columnWidthOrDefault(column),\n }));\n}\n\nfunction columnWidthOrDefault(column: TableColumn): ColumnWidth {\n return (column.props.width ??\n (column.type === \"column.stack\" ? \"xl\" : DEFAULT_COLUMN_WIDTH)) as ColumnWidth;\n}\n\nexport function getTableUtilityTracks(\n hasActions: boolean,\n hasSelection: boolean,\n hasExpander = false,\n) {\n // Utility tracks are fixed because the independent header/filter/body grids would drift with content-sized tracks.\n return {\n leadingTracks: [...(hasExpander ? [\"2.5rem\"] : []), ...(hasSelection ? [\"3rem\"] : [])],\n trailingTracks: hasActions ? [\"10rem\"] : [],\n };\n}\n"],"mappings":";;;;AAMA,SAAgB,cAAc,OAAmB,QAA4C;CAC3F,OAAO,MAAM,MAAM,MAAM,gBAAgB,YAAY,QAAQ,OAAO,GAAG;AACzE;AAEA,SAAgB,kBACd,MACwC;CACxC,IAAI,MAAM,cAAc,OACtB,OAAO;CAGT,IAAI,MAAM,cAAc,QACtB,OAAO;AAIX;AAEA,SAAgB,cAAc,UAAkB,OAA2B;CACzE,MAAM,MAAM,IAAI,IAAI,UAAU,OAAO,SAAS,MAAM;CAEpD,IAAI,MAAM,QAAQ,SAAS,GACzB,IAAI,aAAa,IAAI,UAAU,iBAAiB,KAAK,CAAC;CAGxD,IAAI,MAAM,MAAM,SAAS,GACvB,IAAI,aAAa,IAAI,QAAQ,eAAe,KAAK,CAAC;CAGpD,IAAI,MAAM,WAAW,IACnB,IAAI,aAAa,IAAI,KAAK,MAAM,MAAM;CAGxC,mBAAmB,KAAK,MAAM,YAAY;CAE1C,IAAI,aAAa,IAAI,QAAQ,OAAO,MAAM,IAAI,CAAC;CAC/C,IAAI,aAAa,IAAI,YAAY,OAAO,MAAM,OAAO,CAAC;CAEtD,OAAO,GAAG,IAAI,WAAW,IAAI;AAC/B;AAEA,SAAS,mBAAmB,KAAU,cAA6C;CACjF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,qBAAqB,YAAY,CAAC,GAC1E,uBAAuB,KAAK,MAAM,IAAI,IAAI,KAAK;AAEnD;AAEA,SAAS,qBAAqB,cAAgE;CAC5F,MAAM,SAAkC,CAAC;CAEzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,GAAG;EACvD,MAAM,aAAa,0BAA0B,KAAK;EAElD,IAAI,eAAe,KAAA,GACjB,OAAO,OAAO;CAElB;CAEA,OAAO;AACT;AAEA,SAAS,0BAA0B,OAAqC;CACtE,IAAI,cAAc,KAAK,KAAK,MAAM,QAAQ,KAAK,KAAK,OAAO,UAAU,UACnE;CAGF,MAAM,UAAU,OAAO,QAAQ,KAAK,EACjC,KAAK,CAAC,QAAQ,cAAc,CAAC,QAAQ,2BAA2B,QAAQ,CAAC,CAAU,EACnF,QAAQ,UAA+C,MAAM,OAAO,KAAA,CAAS;CAEhF,OAAO,QAAQ,SAAS,IAAI,OAAO,YAAY,OAAO,IAAI,KAAA;AAC5D;AAEA,SAAS,2BAA2B,OAAqC;CACvE,IAAI,cAAc,KAAK,GACrB;CAGF,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,MAAM,SAAS,MAAM,IAAI,0BAA0B,EAAE,QAAQ,SAAS,SAAS,KAAA,CAAS;EAExF,OAAO,OAAO,SAAS,IAAI,SAAS,KAAA;CACtC;CAEA,IAAI,OAAO,UAAU,UAAU;EAC7B,IAAI,UAAU,MACZ;EAGF,MAAM,UAAU,OAAO,QAAQ,KAAK,EACjC,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,2BAA2B,IAAI,CAAC,CAAU,EACrE,QAAQ,UAA+C,MAAM,OAAO,KAAA,CAAS;EAEhF,OAAO,QAAQ,SAAS,IAAI,OAAO,YAAY,OAAO,IAAI,KAAA;CAC5D;CAEA,OAAO,OAAO,KAAK;AACrB;AAEA,SAAS,uBAAuB,KAAU,KAAa,OAAsB;CAC3E,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,MAAM,QAAQ,OACjB,uBAAuB,KAAK,GAAG,IAAI,KAAK,IAAI;EAG9C;CACF;CAEA,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM;EAC/C,KAAK,MAAM,CAAC,QAAQ,aAAa,OAAO,QAAQ,KAAK,GACnD,uBAAuB,KAAK,GAAG,IAAI,GAAG,OAAO,IAAI,QAAQ;EAG3D;CACF;CAEA,IAAI,aAAa,OAAO,KAAK,OAAO,KAAK,CAAC;AAC5C;AAEA,SAAgB,eAAe,OAA4C;CACzE,MAAM,SAAkC,CAAC;CAEzC,IAAI,MAAM,QAAQ,SAAS,GACzB,OAAO,SAAS,iBAAiB,KAAK;CAGxC,IAAI,MAAM,MAAM,SAAS,GACvB,OAAO,OAAO,eAAe,KAAK;CAGpC,MAAM,eAAe,qBAAqB,MAAM,YAAY;CAE5D,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,OAAO,KAAK;CAGd,IAAI,MAAM,WAAW,IACnB,OAAO,IAAI,MAAM;CAGnB,OAAO;AACT;AAEA,SAAS,iBAAiB,OAA2B;CACnD,OAAO,MAAM,QACV,KAAK,WAAW,GAAG,OAAO,MAAM,GAAG,OAAO,SAAS,GAAG,mBAAmB,OAAO,KAAK,GAAG,EACxF,KAAK,GAAG;AACb;AAEA,SAAS,eAAe,OAA2B;CACjD,OAAO,MAAM,MACV,KAAK,SAAU,KAAK,cAAc,SAAS,IAAI,KAAK,QAAQ,KAAK,GAAI,EACrE,KAAK,GAAG;AACb;AAEA,IAAM,iBAAyC;CAC7C,UAAU;CACV,aAAa;CACb,WAAW;CACX,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACP,QAAQ;AACV;AAEA,IAAa,6BAA6B,IAAI,IAAY,CAAC,SAAS,QAAQ,CAAC;AAE7E,SAAgB,cAAc,UAA0B;CACtD,OAAO,UAAU,WAAW,mBAAmB,YAAY,eAAe,aAAa,QAAQ;AACjG;AAEA,SAAgB,sBAAsB,WAA2B;CAC/D,OAAO,cAAc,SAAS,eAAe;AAC/C;AAEA,SAAgB,SAAS,OAAoB,QAAkC;CAC7E,IAAI,CAAC,OAAO,MAAM,UAChB,OAAO;CAGT,MAAM,cAAc,MAAM,MAAM,SAAS,KAAK,QAAQ,OAAO,GAAG;CAChE,MAAM,iBAAiB,MAAM,QAAQ,SAAS,KAAK,QAAQ,OAAO,GAAG;CAErE,IAAI,CAAC,aACH,OAAO,CAAC,GAAG,OAAO;EAAE,KAAK,OAAO;EAAK,WAAW;CAAM,CAAC;CAGzD,IAAI,YAAY,cAAc,OAC5B,OAAO,CAAC,GAAG,gBAAgB;EAAE,KAAK,OAAO;EAAK,WAAW;CAAO,CAAC;CAGnE,OAAO;AACT;AAEA,SAAgB,gBAAgB,aAAqB,UAA4B;CAC/E,IAAI,YAAY,GACd,OAAO,MAAM,KAAK,EAAE,QAAQ,SAAS,IAAI,GAAG,UAAU,QAAQ,CAAC;CAGjE,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,cAAc,GAAG,WAAW,CAAC,CAAC;CAEjE,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,UAAU,QAAQ,KAAK;AAC9D;AAEA,SAAgB,sBAAsB,SAAwB;CAC5D,OAAO,QAAQ,KAAK,YAAY;EAC9B,KAAK,OAAO;EACZ,OAAO,OAAO,MAAM;EACpB,OAAO,qBAAqB,MAAM;CACpC,EAAE;AACJ;AAEA,SAAS,qBAAqB,QAAkC;CAC9D,OAAQ,OAAO,MAAM,UAClB,OAAO,SAAS,iBAAiB,OAAA;AACtC;AAEA,SAAgB,sBACd,YACA,cACA,cAAc,OACd;CAEA,OAAO;EACL,eAAe,CAAC,GAAI,cAAc,CAAC,QAAQ,IAAI,CAAC,GAAI,GAAI,eAAe,CAAC,MAAM,IAAI,CAAC,CAAE;EACrF,gBAAgB,aAAa,CAAC,OAAO,IAAI,CAAC;CAC5C;AACF"}
|
|
1
|
+
{"version":3,"file":"query.js","names":[],"sources":["../../../resources/js/table/lib/query.ts"],"sourcesContent":["import { translate } from \"@lattice-php/lattice/i18n\";\nimport { DEFAULT_COLUMN_WIDTH } from \"@lattice-php/lattice/core/hooks/column-sizing\";\nimport type { ColumnWidth } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyMember } from \"./filter-values\";\nimport type { TableColumn, TableSort, TableQuery } from \"@lattice-php/lattice/table/types\";\n\nexport function getColumnSort(query: TableQuery, column: TableColumn): TableSort | undefined {\n return query.sorts.find((currentSort) => currentSort.key === column.key);\n}\n\nexport function getColumnAriaSort(\n sort: TableSort | undefined,\n): \"ascending\" | \"descending\" | undefined {\n if (sort?.direction === \"asc\") {\n return \"ascending\";\n }\n\n if (sort?.direction === \"desc\") {\n return \"descending\";\n }\n\n return undefined;\n}\n\nexport function buildEndpoint(endpoint: string, query: TableQuery): string {\n const url = new URL(endpoint, window.location.origin);\n\n if (query.filters.length > 0) {\n url.searchParams.set(\"filter\", serializeFilters(query));\n }\n\n if (query.sorts.length > 0) {\n url.searchParams.set(\"sort\", serializeSorts(query));\n }\n\n if (query.search !== \"\") {\n url.searchParams.set(\"q\", query.search);\n }\n\n appendTableFilters(url, query.tableFilters);\n\n url.searchParams.set(\"page\", String(query.page));\n url.searchParams.set(\"per_page\", String(query.perPage));\n\n return `${url.pathname}${url.search}`;\n}\n\nfunction appendTableFilters(url: URL, tableFilters: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(getTableFilterParams(tableFilters))) {\n appendTableFilterParam(url, `tf[${key}]`, value);\n }\n}\n\nfunction getTableFilterParams(tableFilters: Record<string, unknown>): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(tableFilters)) {\n const normalized = normalizeTableFilterValue(value);\n\n if (normalized !== undefined) {\n params[key] = normalized;\n }\n }\n\n return params;\n}\n\nfunction normalizeTableFilterValue(value: unknown): unknown | undefined {\n if (isEmptyMember(value) || Array.isArray(value) || typeof value !== \"object\") {\n return undefined;\n }\n\n const entries = Object.entries(value)\n .map(([subKey, subValue]) => [subKey, normalizeTableFilterMember(subValue)] as const)\n .filter((entry): entry is readonly [string, unknown] => entry[1] !== undefined);\n\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nfunction normalizeTableFilterMember(value: unknown): unknown | undefined {\n if (isEmptyMember(value)) {\n return undefined;\n }\n\n if (Array.isArray(value)) {\n const values = value.map(normalizeTableFilterMember).filter((item) => item !== undefined);\n\n return values.length > 0 ? values : undefined;\n }\n\n if (typeof value === \"object\") {\n if (value === null) {\n return undefined;\n }\n\n const entries = Object.entries(value)\n .map(([key, item]) => [key, normalizeTableFilterMember(item)] as const)\n .filter((entry): entry is readonly [string, unknown] => entry[1] !== undefined);\n\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n }\n\n return String(value);\n}\n\nfunction appendTableFilterParam(url: URL, key: string, value: unknown): void {\n if (Array.isArray(value)) {\n for (const item of value) {\n appendTableFilterParam(url, `${key}[]`, item);\n }\n\n return;\n }\n\n if (typeof value === \"object\" && value !== null) {\n for (const [subKey, subValue] of Object.entries(value)) {\n appendTableFilterParam(url, `${key}[${subKey}]`, subValue);\n }\n\n return;\n }\n\n url.searchParams.append(key, String(value));\n}\n\nexport function getQueryParams(query: TableQuery): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (query.filters.length > 0) {\n params.filter = serializeFilters(query);\n }\n\n if (query.sorts.length > 0) {\n params.sort = serializeSorts(query);\n }\n\n const tableFilters = getTableFilterParams(query.tableFilters);\n\n if (Object.keys(tableFilters).length > 0) {\n params.tf = tableFilters;\n }\n\n if (query.search !== \"\") {\n params.q = query.search;\n }\n\n return params;\n}\n\nfunction serializeFilters(query: TableQuery): string {\n return query.filters\n .map((clause) => `${clause.field}:${clause.operator}:${encodeURIComponent(clause.value)}`)\n .join(\",\");\n}\n\nfunction serializeSorts(query: TableQuery): string {\n return query.sorts\n .map((sort) => (sort.direction === \"desc\" ? `-${sort.key}` : sort.key))\n .join(\",\");\n}\n\nconst operatorLabels: Record<string, string> = {\n contains: \"contains\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n eq: \"equals\",\n neq: \"not equals\",\n gt: \">\",\n gte: \"≥\",\n lt: \"<\",\n lte: \"≤\",\n in: \"in\",\n not_in: \"not in\",\n before: \"before\",\n after: \"after\",\n empty: \"is empty\",\n filled: \"is not empty\",\n};\n\nexport const VALUELESS_FILTER_OPERATORS = new Set<string>([\"empty\", \"filled\"]);\n\nexport function operatorLabel(operator: string): string {\n return translate(\"lattice\", `table.operators.${operator}`, operatorLabels[operator] ?? operator);\n}\n\nexport function getSortDirectionLabel(direction: string): string {\n return direction === \"desc\" ? \"descending\" : \"ascending\";\n}\n\nexport function nextSort(sorts: TableSort[], column: TableColumn): TableSort[] {\n if (!column.props.sortable) {\n return sorts;\n }\n\n const currentSort = sorts.find((sort) => sort.key === column.key);\n const remainingSorts = sorts.filter((sort) => sort.key !== column.key);\n\n if (!currentSort) {\n return [...sorts, { key: column.key, direction: \"asc\" }];\n }\n\n if (currentSort.direction === \"asc\") {\n return [...remainingSorts, { key: column.key, direction: \"desc\" }];\n }\n\n return remainingSorts;\n}\n\nexport function getVisiblePages(currentPage: number, lastPage: number): number[] {\n if (lastPage <= 5) {\n return Array.from({ length: lastPage }, (_, index) => index + 1);\n }\n\n const start = Math.max(1, Math.min(currentPage - 2, lastPage - 4));\n\n return Array.from({ length: 5 }, (_, index) => start + index);\n}\n\nexport function getTableSizingColumns(columns: TableColumn[]) {\n return columns.map((column) => ({\n key: column.key,\n label: column.props.label,\n width: columnWidthOrDefault(column),\n }));\n}\n\nfunction columnWidthOrDefault(column: TableColumn): ColumnWidth {\n return (column.props.width ?? DEFAULT_COLUMN_WIDTH) as ColumnWidth;\n}\n\nexport function getTableUtilityTracks(\n hasActions: boolean,\n hasSelection: boolean,\n hasExpander = false,\n) {\n // Utility tracks are fixed because the independent header/filter/body grids would drift with content-sized tracks.\n return {\n leadingTracks: [...(hasExpander ? [\"2.5rem\"] : []), ...(hasSelection ? [\"3rem\"] : [])],\n trailingTracks: hasActions ? [\"10rem\"] : [],\n };\n}\n"],"mappings":"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"}
|
package/dist/table/plugin.d.ts
CHANGED
package/dist/table/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/table/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type {
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/table/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { TableNodeType } from \"@lattice-php/lattice/types/generated\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport TableComponent from \"./components/table\";\n\n// The table renders an enriched TableNode (rows/pagination/state the server\n// hydrates onto it); the registry erases per-component node types here.\nexport const tableComponents = createPlugin({\n components: {\n table: eagerComponent(TableComponent as unknown as RendererComponent<\"table\">),\n } satisfies ComponentRegistryFor<TableNodeType>,\n name: \"lattice/table\",\n});\n"],"mappings":";;;AAWA,IAAa,kBAAkB,aAAa;CAC1C,YAAY,EACV,OAAO,eAAe,cAAuD,EAC/E;CACA,MAAM;AACR,CAAC"}
|
package/dist/table/types.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { NodeUnionOf
|
|
2
|
-
import { ActionNodeType, ColumnFilter,
|
|
3
|
-
export type { ColumnFilter,
|
|
1
|
+
import { NodeUnionOf } from '../core/types.js';
|
|
2
|
+
import { ActionNodeType, ColumnFilter, ColumnNode, ColumnProps, ColumnPropsOf, ColumnNodeType, CommonColumnProps, FilterClause, FilterIndicator, FilterNode, FilterNodeType, FilterProps, FilterPropsOf, Table, TablePagination, TableQuery, TableResult, TableSort } from '../types/generated.js';
|
|
3
|
+
export type { ColumnFilter, ColumnNode, ColumnProps, ColumnPropsOf, ColumnNodeType, CommonColumnProps, FilterClause, FilterIndicator, FilterNode, FilterNodeType, FilterProps, FilterPropsOf, TablePagination, TableQuery, TableResult, TableSort, };
|
|
4
4
|
export type ActionNode = NodeUnionOf<ActionNodeType>;
|
|
5
5
|
export type TableRow = Record<string, unknown>;
|
|
6
|
-
export type TableNodeProps = Partial<
|
|
7
|
-
bulkActions?: ActionNode[];
|
|
8
|
-
columns?: ColumnNode[];
|
|
6
|
+
export type TableNodeProps = Partial<Table> & {
|
|
9
7
|
data?: TableRow[];
|
|
10
|
-
filters?: FilterNode[];
|
|
11
8
|
pagination?: TablePagination;
|
|
12
9
|
query?: Partial<TableQuery>;
|
|
13
10
|
};
|
|
@@ -17,54 +14,4 @@ export type TableNode = {
|
|
|
17
14
|
key?: string;
|
|
18
15
|
props?: TableNodeProps;
|
|
19
16
|
};
|
|
20
|
-
/**
|
|
21
|
-
* Consumer apps augment this via `declare module "@lattice-php/lattice"` to type
|
|
22
|
-
* their custom columns' props; built-ins resolve through `ColumnPropsMap`. The
|
|
23
|
-
* column counterpart of `ComponentProps`.
|
|
24
|
-
*/
|
|
25
|
-
export interface ColumnProps {
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* The base `Column` props every column node carries on the wire regardless of
|
|
29
|
-
* type — custom columns extend `Column`, so the unaugmented fallback carries
|
|
30
|
-
* them too. Derived from the generated types (each built-in bakes them in)
|
|
31
|
-
* rather than hand-written.
|
|
32
|
-
*/
|
|
33
|
-
export type CommonColumnProps = Pick<ColumnPropsMap["column.text"], "label" | "width" | "align" | "sortable" | "toggleable" | "hiddenByDefault" | "filter">;
|
|
34
|
-
export type ColumnPropsOf<TType extends string> = ResolveProps<ColumnProps, ColumnPropsMap, TType, CommonColumnProps & Record<string, unknown>>;
|
|
35
|
-
/**
|
|
36
|
-
* A column node, authored and consumed like a field/component: `key`/`type`
|
|
37
|
-
* stay top-level, every common concern (`label`/`width`/`filter`/…) lives in
|
|
38
|
-
* `props` on each generated column type. `schema` is only present for a
|
|
39
|
-
* `StackColumn`: the bound component nodes rendered per row (see
|
|
40
|
-
* `materializeSchema`). The column counterpart of `NodeOfType`.
|
|
41
|
-
*/
|
|
42
|
-
export type ColumnNode<TType extends string = string> = {
|
|
43
|
-
type: TType;
|
|
44
|
-
key: string;
|
|
45
|
-
props: ColumnPropsOf<TType>;
|
|
46
|
-
schema?: Schema;
|
|
47
|
-
};
|
|
48
17
|
export type TableColumn = ColumnNode;
|
|
49
|
-
/**
|
|
50
|
-
* Consumer apps augment this via `declare module` to type their custom filters'
|
|
51
|
-
* props. Schema-based filters no longer need custom client props, but the map
|
|
52
|
-
* remains for existing custom controls during the migration.
|
|
53
|
-
*/
|
|
54
|
-
export interface FilterProps {
|
|
55
|
-
}
|
|
56
|
-
export type FilterPropsOf<TType extends string> = ResolveProps<FilterProps, FilterPropsMap, TType, Record<string, unknown>>;
|
|
57
|
-
export type FilterNodeType = keyof FilterPropsMap & string;
|
|
58
|
-
/**
|
|
59
|
-
* A dedicated table filter, authored and consumed like a field/component:
|
|
60
|
-
* `key`/`type` stay top-level, `props` carries `label` plus whatever the
|
|
61
|
-
* filter type contributes. `schema` is the bound field(s) rendering the
|
|
62
|
-
* filter's control and is absent when empty. The filter counterpart of
|
|
63
|
-
* `ColumnNode`.
|
|
64
|
-
*/
|
|
65
|
-
export type FilterNode<TType extends string = FilterNodeType> = {
|
|
66
|
-
type: TType;
|
|
67
|
-
key: string;
|
|
68
|
-
props: FilterPropsOf<TType>;
|
|
69
|
-
schema?: WireNode[];
|
|
70
|
-
};
|
package/dist/toast/callout.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callout.js","names":[],"sources":["../../resources/js/toast/callout.ts"],"sourcesContent":["import type { Callout } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/
|
|
1
|
+
{"version":3,"file":"callout.js","names":[],"sources":["../../resources/js/toast/callout.ts"],"sourcesContent":["import type { Callout } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { isVariant } from \"./toast\";\n\nexport type { Callout };\n\nexport function normalizeCallout(detail: unknown): Callout | null {\n if (typeof detail !== \"object\" || detail === null) {\n return null;\n }\n\n const callout = detail as Record<string, unknown>;\n\n if (typeof callout.message !== \"string\" || callout.message === \"\") {\n return null;\n }\n\n return {\n action: (callout.action as Callout[\"action\"]) ?? null,\n dismissible: callout.dismissible !== false,\n message: callout.message,\n title: typeof callout.title === \"string\" ? callout.title : null,\n variant: isVariant(callout.variant) ? callout.variant : \"info\",\n };\n}\n\nexport function onCallout(callback: (callout: Callout) => void): () => void {\n const listener = (event: Event): void => {\n const callout = normalizeCallout((event as CustomEvent).detail);\n\n if (callout) {\n callback(callout);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.callout, listener);\n\n return () => window.removeEventListener(LATTICE_EVENT.callout, listener);\n}\n"],"mappings":";;;AAMA,SAAgB,iBAAiB,QAAiC;CAChE,IAAI,OAAO,WAAW,YAAY,WAAW,MAC3C,OAAO;CAGT,MAAM,UAAU;CAEhB,IAAI,OAAO,QAAQ,YAAY,YAAY,QAAQ,YAAY,IAC7D,OAAO;CAGT,OAAO;EACL,QAAS,QAAQ,UAAgC;EACjD,aAAa,QAAQ,gBAAgB;EACrC,SAAS,QAAQ;EACjB,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;EAC3D,SAAS,UAAU,QAAQ,OAAO,IAAI,QAAQ,UAAU;CAC1D;AACF;AAEA,SAAgB,UAAU,UAAkD;CAC1E,MAAM,YAAY,UAAuB;EACvC,MAAM,UAAU,iBAAkB,MAAsB,MAAM;EAE9D,IAAI,SACF,SAAS,OAAO;CAEpB;CAEA,OAAO,iBAAiB,cAAc,SAAS,QAAQ;CAEvD,aAAa,OAAO,oBAAoB,cAAc,SAAS,QAAQ;AACzE"}
|