@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
package/dist/registry.d.ts
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
+
import { ActionNodeType, ChatNodeType, FormNodeType, FragmentNodeType, LayoutNodeType, NodeType, NotificationNodeType, RemoteNodeType, TableNodeType, UiNodeType } from './types/generated.js';
|
|
2
|
+
type RegisteredNodeType = ActionNodeType | ChatNodeType | FormNodeType | FragmentNodeType | LayoutNodeType | NotificationNodeType | RemoteNodeType | TableNodeType | UiNodeType;
|
|
3
|
+
type Assert<T extends true> = T;
|
|
4
|
+
export type AllNodeTypesRegistered = Assert<Exclude<NodeType, RegisteredNodeType> extends never ? true : false>;
|
|
1
5
|
export declare const registry: import('./core/registry.js').Registry;
|
|
6
|
+
export {};
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../resources/js/registry.ts"],"sourcesContent":["import { createRegistry } from \"@lattice-php/lattice/core/registry\";\nimport { actionComponents } from \"./action/plugin\";\nimport { chatComponents } from \"./chat/plugin\";\nimport { uiComponents } from \"./ui/plugin\";\nimport { formComponents } from \"./form/plugin\";\nimport { layoutComponents } from \"./layout/plugin\";\nimport { notificationsComponents } from \"./notifications/plugin\";\nimport { remoteComponents } from \"./remote/plugin\";\nimport { tableComponents } from \"./table/plugin\";\n\nexport const registry = createRegistry(\n uiComponents,\n actionComponents,\n formComponents,\n layoutComponents,\n tableComponents,\n chatComponents,\n notificationsComponents,\n remoteComponents,\n);\n"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"registry.js","names":[],"sources":["../resources/js/registry.ts"],"sourcesContent":["import { createRegistry } from \"@lattice-php/lattice/core/registry\";\nimport type {\n ActionNodeType,\n ChatNodeType,\n FormNodeType,\n FragmentNodeType,\n LayoutNodeType,\n NodeType,\n NotificationNodeType,\n RemoteNodeType,\n TableNodeType,\n UiNodeType,\n} from \"@lattice-php/lattice/types/generated\";\nimport { actionComponents } from \"./action/plugin\";\nimport { chatComponents } from \"./chat/plugin\";\nimport { uiComponents } from \"./ui/plugin\";\nimport { formComponents } from \"./form/plugin\";\nimport { layoutComponents } from \"./layout/plugin\";\nimport { notificationsComponents } from \"./notifications/plugin\";\nimport { remoteComponents } from \"./remote/plugin\";\nimport { tableComponents } from \"./table/plugin\";\n\n// Compile-time totality: every generated NodeType must belong to a registered\n// plugin's union. A new PHP domain fails here until its plugin exists.\ntype RegisteredNodeType =\n | ActionNodeType\n | ChatNodeType\n | FormNodeType\n | FragmentNodeType\n | LayoutNodeType\n | NotificationNodeType\n | RemoteNodeType\n | TableNodeType\n | UiNodeType;\ntype Assert<T extends true> = T;\nexport type AllNodeTypesRegistered = Assert<\n Exclude<NodeType, RegisteredNodeType> extends never ? true : false\n>;\n\nexport const registry = createRegistry(\n uiComponents,\n actionComponents,\n formComponents,\n layoutComponents,\n tableComponents,\n chatComponents,\n notificationsComponents,\n remoteComponents,\n);\n"],"mappings":";;;;;;;;;;AAuCA,IAAa,WAAW,eACtB,cACA,kBACA,gBACA,kBACA,iBACA,gBACA,yBACA,gBACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { materializeSchema } from "../../core/materialize.js";
|
|
1
2
|
import { Renderer } from "../../core/renderer.js";
|
|
2
3
|
import { useT } from "../../i18n/instance.js";
|
|
3
4
|
import { remoteJson } from "../../core/api.js";
|
|
4
|
-
import { materializeSchema } from "../../core/materialize.js";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region resources/js/remote/components/data-list.tsx
|
package/dist/remote/plugin.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/remote/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/remote/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { RemoteNodeType } from \"@lattice-php/lattice/types/generated\";\nimport DataListComponent from \"./components/data-list\";\n\nexport const remoteComponents = createPlugin({\n components: {\n \"remote.data-list\": eagerComponent(DataListComponent),\n } satisfies ComponentRegistryFor<RemoteNodeType>,\n name: \"lattice/remote\",\n});\n"],"mappings":";;;AAQA,IAAa,mBAAmB,aAAa;CAC3C,YAAY,EACV,oBAAoB,eAAe,QAAiB,EACtD;CACA,MAAM;AACR,CAAC"}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { useT } from "../../i18n/instance.js";
|
|
2
|
-
import { withHeaders } from "../../core/headers.js";
|
|
3
2
|
import { prefixedTestId } from "../../core/test-id.js";
|
|
4
|
-
import { getActionEffects } from "../../effects/dispatch.js";
|
|
5
3
|
import { useEffectDispatcher } from "../../effects/use-effect-dispatcher.js";
|
|
6
4
|
import { Button } from "../../ui/button.js";
|
|
7
5
|
import { Spinner } from "../../ui/spinner.js";
|
|
8
6
|
import { ConfirmDialog } from "../../ui/confirm-dialog.js";
|
|
7
|
+
import { apiFetch } from "../../core/api.js";
|
|
9
8
|
import { runAction } from "../../action/lib/run-action.js";
|
|
10
9
|
import { ActionForm } from "../../action/components/action-form.js";
|
|
11
|
-
import { useHttp } from "@inertiajs/react";
|
|
12
10
|
import { useState } from "react";
|
|
13
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
12
|
//#region resources/js/table/components/bulk-bar.tsx
|
|
15
13
|
function BulkBar({ actions, selectedKeys, allMatching, total, query, canSelectAllMatching, onSelectAllMatching, onCompleted }) {
|
|
16
14
|
const { t } = useT("lattice");
|
|
17
|
-
const
|
|
15
|
+
const [processing, setProcessing] = useState(false);
|
|
18
16
|
const dispatch = useEffectDispatcher();
|
|
19
17
|
const [confirming, setConfirming] = useState(null);
|
|
20
18
|
const [filling, setFilling] = useState(null);
|
|
@@ -23,11 +21,15 @@ function BulkBar({ actions, selectedKeys, allMatching, total, query, canSelectAl
|
|
|
23
21
|
...query
|
|
24
22
|
} : { selected: selectedKeys };
|
|
25
23
|
async function submit(action) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
setProcessing(true);
|
|
25
|
+
const ok = await runAction(() => apiFetch(action.endpoint, {
|
|
26
|
+
method: action.method,
|
|
27
|
+
ref: action.ref,
|
|
28
|
+
body: JSON.stringify(selectionPayload()),
|
|
29
|
+
throwOnError: false
|
|
30
|
+
}), dispatch);
|
|
31
|
+
setProcessing(false);
|
|
32
|
+
if (ok) {
|
|
31
33
|
setConfirming(null);
|
|
32
34
|
onCompleted();
|
|
33
35
|
}
|
|
@@ -64,9 +66,9 @@ function BulkBar({ actions, selectedKeys, allMatching, total, query, canSelectAl
|
|
|
64
66
|
type: "button",
|
|
65
67
|
"data-test": prefixedTestId("bulk-action", action.id),
|
|
66
68
|
variant: action.variant,
|
|
67
|
-
disabled:
|
|
69
|
+
disabled: processing,
|
|
68
70
|
onClick: () => run(action),
|
|
69
|
-
children: [
|
|
71
|
+
children: [processing && /* @__PURE__ */ jsx(Spinner, {}), action.label]
|
|
70
72
|
}, action.id))
|
|
71
73
|
}),
|
|
72
74
|
confirming?.confirmation && /* @__PURE__ */ jsx(ConfirmDialog, {
|
|
@@ -75,7 +77,7 @@ function BulkBar({ actions, selectedKeys, allMatching, total, query, canSelectAl
|
|
|
75
77
|
confirmLabel: confirming.confirmation.confirmLabel ?? confirming.label,
|
|
76
78
|
cancelLabel: confirming.confirmation.cancelLabel ?? t("common.cancel", "Cancel"),
|
|
77
79
|
confirmVariant: confirming.variant,
|
|
78
|
-
processing
|
|
80
|
+
processing,
|
|
79
81
|
onConfirm: () => void submit(confirming),
|
|
80
82
|
onCancel: () => setConfirming(null)
|
|
81
83
|
}),
|
|
@@ -88,13 +90,14 @@ function BulkBar({ actions, selectedKeys, allMatching, total, query, canSelectAl
|
|
|
88
90
|
formNode: filling.form,
|
|
89
91
|
method: filling.method,
|
|
90
92
|
onClose: () => setFilling(null),
|
|
91
|
-
onSuccess: (
|
|
92
|
-
dispatch(getActionEffects(response.effects));
|
|
93
|
+
onSuccess: () => {
|
|
93
94
|
setFilling(null);
|
|
94
95
|
onCompleted();
|
|
95
96
|
},
|
|
97
|
+
placement: filling.modalSide ?? "center",
|
|
96
98
|
submitLabel: filling.confirmation?.confirmLabel ?? filling.label,
|
|
97
|
-
title: filling.confirmation?.title ?? filling.label
|
|
99
|
+
title: filling.confirmation?.title ?? filling.label,
|
|
100
|
+
width: filling.modalWidth ?? void 0
|
|
98
101
|
})
|
|
99
102
|
]
|
|
100
103
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bulk-bar.js","names":[],"sources":["../../../resources/js/table/components/bulk-bar.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"bulk-bar.js","names":[],"sources":["../../../resources/js/table/components/bulk-bar.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { ActionForm, runAction } from \"@lattice-php/lattice/action\";\nimport { apiFetch } from \"@lattice-php/lattice/core/api\";\nimport { useEffectDispatcher } from \"@lattice-php/lattice/effects/use-effect-dispatcher\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { ConfirmDialog } from \"@lattice-php/lattice/ui/confirm-dialog\";\nimport { Spinner } from \"@lattice-php/lattice/ui/spinner\";\nimport { prefixedTestId } from \"@lattice-php/lattice/core/test-id\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { BulkAction } from \"@lattice-php/lattice/table/lib/bulk\";\n\nexport function BulkBar({\n actions,\n selectedKeys,\n allMatching,\n total,\n query,\n canSelectAllMatching,\n onSelectAllMatching,\n onCompleted,\n}: {\n actions: BulkAction[];\n selectedKeys: string[];\n allMatching: boolean;\n total?: number;\n query: Record<string, unknown>;\n canSelectAllMatching: boolean;\n onSelectAllMatching: () => void;\n onCompleted: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const [processing, setProcessing] = useState(false);\n const dispatch = useEffectDispatcher();\n const [confirming, setConfirming] = useState<BulkAction | null>(null);\n const [filling, setFilling] = useState<BulkAction | null>(null);\n\n const selectionPayload = (): Record<string, unknown> =>\n allMatching ? { allMatching: true, ...query } : { selected: selectedKeys };\n\n async function submit(action: BulkAction): Promise<void> {\n setProcessing(true);\n\n const ok = await runAction(\n () =>\n apiFetch(action.endpoint, {\n method: action.method,\n ref: action.ref,\n body: JSON.stringify(selectionPayload()),\n throwOnError: false,\n }),\n dispatch,\n );\n\n setProcessing(false);\n\n if (ok) {\n setConfirming(null);\n onCompleted();\n }\n }\n\n function run(action: BulkAction): void {\n if (action.form) {\n setFilling(action);\n\n return;\n }\n\n if (action.confirmation) {\n setConfirming(action);\n\n return;\n }\n\n void submit(action);\n }\n\n const count = allMatching ? (total ?? selectedKeys.length) : selectedKeys.length;\n\n return (\n <div className=\"flex flex-wrap items-center gap-3 border-b border-lt-border bg-lt-muted/50 p-4 text-sm\">\n <span className=\"font-medium\">\n {allMatching\n ? t(\"table.bulk.all-selected\", \"All {{count}} selected\", { count })\n : t(\"table.bulk.selected\", \"{{count}} selected\", { count })}\n </span>\n {canSelectAllMatching && (\n <button\n type=\"button\"\n data-test=\"bulk-select-all-matching\"\n className=\"font-medium text-lt-primary underline underline-offset-2\"\n onClick={onSelectAllMatching}\n >\n {t(\"table.bulk.select-all-matching\", \"Select all {{total}} matching\", { total })}\n </button>\n )}\n <div className=\"flex flex-wrap items-center gap-2\">\n {actions.map((action) => (\n <Button\n key={action.id}\n type=\"button\"\n data-test={prefixedTestId(\"bulk-action\", action.id)}\n variant={action.variant}\n disabled={processing}\n onClick={() => run(action)}\n >\n {processing && <Spinner />}\n {action.label}\n </Button>\n ))}\n </div>\n\n {confirming?.confirmation && (\n <ConfirmDialog\n title={confirming.confirmation.title ?? confirming.label}\n description={confirming.confirmation.description ?? undefined}\n confirmLabel={confirming.confirmation.confirmLabel ?? confirming.label}\n cancelLabel={confirming.confirmation.cancelLabel ?? t(\"common.cancel\", \"Cancel\")}\n confirmVariant={confirming.variant}\n processing={processing}\n onConfirm={() => void submit(confirming)}\n onCancel={() => setConfirming(null)}\n />\n )}\n\n {filling?.form && (\n <ActionForm\n cancelLabel={filling.confirmation?.cancelLabel ?? t(\"common.cancel\", \"Cancel\")}\n componentRef={filling.ref}\n description={filling.confirmation?.description ?? undefined}\n endpoint={filling.endpoint}\n extraData={selectionPayload()}\n formNode={filling.form}\n method={filling.method}\n onClose={() => setFilling(null)}\n onSuccess={() => {\n setFilling(null);\n onCompleted();\n }}\n placement={filling.modalSide ?? \"center\"}\n submitLabel={filling.confirmation?.confirmLabel ?? filling.label}\n title={filling.confirmation?.title ?? filling.label}\n width={filling.modalWidth ?? undefined}\n />\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,QAAQ,EACtB,SACA,cACA,aACA,OACA,OACA,sBACA,qBACA,eAUC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAClD,MAAM,WAAW,oBAAoB;CACrC,MAAM,CAAC,YAAY,iBAAiB,SAA4B,IAAI;CACpE,MAAM,CAAC,SAAS,cAAc,SAA4B,IAAI;CAE9D,MAAM,yBACJ,cAAc;EAAE,aAAa;EAAM,GAAG;CAAM,IAAI,EAAE,UAAU,aAAa;CAE3E,eAAe,OAAO,QAAmC;EACvD,cAAc,IAAI;EAElB,MAAM,KAAK,MAAM,gBAEb,SAAS,OAAO,UAAU;GACxB,QAAQ,OAAO;GACf,KAAK,OAAO;GACZ,MAAM,KAAK,UAAU,iBAAiB,CAAC;GACvC,cAAc;EAChB,CAAC,GACH,QACF;EAEA,cAAc,KAAK;EAEnB,IAAI,IAAI;GACN,cAAc,IAAI;GAClB,YAAY;EACd;CACF;CAEA,SAAS,IAAI,QAA0B;EACrC,IAAI,OAAO,MAAM;GACf,WAAW,MAAM;GAEjB;EACF;EAEA,IAAI,OAAO,cAAc;GACvB,cAAc,MAAM;GAEpB;EACF;EAEA,OAAY,MAAM;CACpB;CAEA,MAAM,QAAQ,cAAe,SAAS,aAAa,SAAU,aAAa;CAE1E,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,oBAAC,QAAD;IAAM,WAAU;cACb,cACG,EAAE,2BAA2B,0BAA0B,EAAE,MAAM,CAAC,IAChE,EAAE,uBAAuB,sBAAsB,EAAE,MAAM,CAAC;GACxD,CAAA;GACL,wBACC,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,SAAS;cAER,EAAE,kCAAkC,iCAAiC,EAAE,MAAM,CAAC;GACzE,CAAA;GAEV,oBAAC,OAAD;IAAK,WAAU;cACZ,QAAQ,KAAK,WACZ,qBAAC,QAAD;KAEE,MAAK;KACL,aAAW,eAAe,eAAe,OAAO,EAAE;KAClD,SAAS,OAAO;KAChB,UAAU;KACV,eAAe,IAAI,MAAM;eAN3B,CAQG,cAAc,oBAAC,SAAD,CAAU,CAAA,GACxB,OAAO,KACF;OATD,OAAO,EASN,CACT;GACE,CAAA;GAEJ,YAAY,gBACX,oBAAC,eAAD;IACE,OAAO,WAAW,aAAa,SAAS,WAAW;IACnD,aAAa,WAAW,aAAa,eAAe,KAAA;IACpD,cAAc,WAAW,aAAa,gBAAgB,WAAW;IACjE,aAAa,WAAW,aAAa,eAAe,EAAE,iBAAiB,QAAQ;IAC/E,gBAAgB,WAAW;IACf;IACZ,iBAAiB,KAAK,OAAO,UAAU;IACvC,gBAAgB,cAAc,IAAI;GACnC,CAAA;GAGF,SAAS,QACR,oBAAC,YAAD;IACE,aAAa,QAAQ,cAAc,eAAe,EAAE,iBAAiB,QAAQ;IAC7E,cAAc,QAAQ;IACtB,aAAa,QAAQ,cAAc,eAAe,KAAA;IAClD,UAAU,QAAQ;IAClB,WAAW,iBAAiB;IAC5B,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IAChB,eAAe,WAAW,IAAI;IAC9B,iBAAiB;KACf,WAAW,IAAI;KACf,YAAY;IACd;IACA,WAAW,QAAQ,aAAa;IAChC,aAAa,QAAQ,cAAc,gBAAgB,QAAQ;IAC3D,OAAO,QAAQ,cAAc,SAAS,QAAQ;IAC9C,OAAO,QAAQ,cAAc,KAAA;GAC9B,CAAA;EAEA;;AAET"}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { Icon } from "../../../icons/sprite.js";
|
|
3
3
|
import { useT } from "../../../i18n/instance.js";
|
|
4
|
+
import { isTruthy } from "../../../lib/is-truthy.js";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
5
6
|
//#region resources/js/table/components/cells/boolean-cell.tsx
|
|
6
|
-
function isTruthy(value) {
|
|
7
|
-
return value === true || value === 1 || value === "1" || value === "true";
|
|
8
|
-
}
|
|
9
7
|
var BooleanCell = ({ value }) => {
|
|
10
8
|
const { t } = useT("lattice");
|
|
11
9
|
const truthy = isTruthy(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/boolean-cell.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport {
|
|
1
|
+
{"version":3,"file":"boolean-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/boolean-cell.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { isTruthy } from \"@lattice-php/lattice/lib/is-truthy\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { ColumnCellComponent } from \"@lattice-php/lattice/table/registry\";\n\nexport const BooleanCell: ColumnCellComponent<\"column.boolean\"> = ({ value }) => {\n const { t } = useT(\"lattice\");\n const truthy = isTruthy(value);\n\n return (\n <span aria-label={truthy ? t(\"common.yes\", \"Yes\") : t(\"common.no\", \"No\")} role=\"img\">\n <Icon\n name={truthy ? \"check\" : \"x\"}\n className={cn(\"size-lt-icon-md\", truthy ? \"text-lt-success\" : \"text-lt-muted-fg\")}\n />\n </span>\n );\n};\n"],"mappings":";;;;;;AAMA,IAAa,eAAsD,EAAE,YAAY;CAC/E,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,SAAS,SAAS,KAAK;CAE7B,OACE,oBAAC,QAAD;EAAM,cAAY,SAAS,EAAE,cAAc,KAAK,IAAI,EAAE,aAAa,IAAI;EAAG,MAAK;YAC7E,oBAAC,MAAD;GACE,MAAM,SAAS,UAAU;GACzB,WAAW,GAAG,mBAAmB,SAAS,oBAAoB,kBAAkB;EACjF,CAAA;CACG,CAAA;AAEV"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TableColumn } from '../../types.js';
|
|
3
|
+
/** Wrap cell content in a copy-to-clipboard affordance when `copyable` is set. */
|
|
4
|
+
export declare function CopyableCell({ children, column, copyable, value, }: {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
column: TableColumn;
|
|
7
|
+
copyable?: boolean | null;
|
|
8
|
+
value: string;
|
|
9
|
+
}): ReactNode;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CopyableText } from "../../../ui/copyable-text.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region resources/js/table/components/cells/copyable-cell.tsx
|
|
4
|
+
/** Wrap cell content in a copy-to-clipboard affordance when `copyable` is set. */
|
|
5
|
+
function CopyableCell({ children, column, copyable, value }) {
|
|
6
|
+
if (!copyable) return children;
|
|
7
|
+
return /* @__PURE__ */ jsx(CopyableText, {
|
|
8
|
+
value,
|
|
9
|
+
label: column.props.label ?? column.key,
|
|
10
|
+
testId: `copy-${column.key}`,
|
|
11
|
+
children
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { CopyableCell };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=copyable-cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyable-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/copyable-cell.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { CopyableText } from \"@lattice-php/lattice/ui/copyable-text\";\nimport type { TableColumn } from \"@lattice-php/lattice/table/types\";\n\n/** Wrap cell content in a copy-to-clipboard affordance when `copyable` is set. */\nexport function CopyableCell({\n children,\n column,\n copyable,\n value,\n}: {\n children: ReactNode;\n column: TableColumn;\n copyable?: boolean | null;\n value: string;\n}): ReactNode {\n if (!copyable) {\n return children;\n }\n\n return (\n <CopyableText\n value={value}\n label={column.props.label ?? column.key}\n testId={`copy-${column.key}`}\n >\n {children}\n </CopyableText>\n );\n}\n"],"mappings":";;;;AAKA,SAAgB,aAAa,EAC3B,UACA,QACA,UACA,SAMY;CACZ,IAAI,CAAC,UACH,OAAO;CAGT,OACE,oBAAC,cAAD;EACS;EACP,OAAO,OAAO,MAAM,SAAS,OAAO;EACpC,QAAQ,QAAQ,OAAO;EAEtB;CACW,CAAA;AAElB"}
|
|
@@ -1,32 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CopyableText } from "../../../ui/copyable-text.js";
|
|
3
|
-
import { formatCell } from "../../lib/format.js";
|
|
4
|
-
import { numericValue } from "../../../format/numeric.js";
|
|
5
|
-
import { formatNumber } from "../../../format/number.js";
|
|
1
|
+
import { NumericCell } from "./numeric-cell.js";
|
|
6
2
|
import { jsx } from "react/jsx-runtime";
|
|
7
3
|
//#region resources/js/table/components/cells/money-cell.tsx
|
|
8
4
|
var MoneyCell = ({ column, props, row, value }) => {
|
|
9
|
-
const { locale } = useLocale();
|
|
10
|
-
if (numericValue(value) === null) return /* @__PURE__ */ jsx("span", { children: formatCell(value, column) });
|
|
11
5
|
const rawCode = props.currencyField ? row[props.currencyField] : void 0;
|
|
12
6
|
const code = props.currency ?? (typeof rawCode === "string" ? rawCode : null);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
return /* @__PURE__ */ jsx(NumericCell, {
|
|
8
|
+
column,
|
|
9
|
+
copyable: props.copyable,
|
|
10
|
+
value,
|
|
11
|
+
format: {
|
|
16
12
|
kind: "number",
|
|
17
13
|
notation: "standard",
|
|
18
14
|
minimumFractionDigits: props.minimumFractionDigits,
|
|
19
15
|
maximumFractionDigits: props.maximumFractionDigits,
|
|
20
16
|
currency: code,
|
|
21
17
|
unit: null
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
if (!props.copyable) return content;
|
|
25
|
-
return /* @__PURE__ */ jsx(CopyableText, {
|
|
26
|
-
value: String(value),
|
|
27
|
-
label: column.props.label ?? column.key,
|
|
28
|
-
testId: `copy-${column.key}`,
|
|
29
|
-
children: content
|
|
18
|
+
}
|
|
30
19
|
});
|
|
31
20
|
};
|
|
32
21
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/money-cell.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"money-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/money-cell.tsx"],"sourcesContent":["import type { ColumnCellComponent } from \"@lattice-php/lattice/table/registry\";\nimport { NumericCell } from \"./numeric-cell\";\n\nexport const MoneyCell: ColumnCellComponent<\"column.money\"> = ({ column, props, row, value }) => {\n const rawCode = props.currencyField ? row[props.currencyField] : undefined;\n const code = props.currency ?? (typeof rawCode === \"string\" ? rawCode : null);\n\n return (\n <NumericCell\n column={column}\n copyable={props.copyable}\n value={value}\n format={{\n kind: \"number\",\n notation: \"standard\",\n minimumFractionDigits: props.minimumFractionDigits,\n maximumFractionDigits: props.maximumFractionDigits,\n currency: code,\n unit: null,\n }}\n />\n );\n};\n"],"mappings":";;;AAGA,IAAa,aAAkD,EAAE,QAAQ,OAAO,KAAK,YAAY;CAC/F,MAAM,UAAU,MAAM,gBAAgB,IAAI,MAAM,iBAAiB,KAAA;CACjE,MAAM,OAAO,MAAM,aAAa,OAAO,YAAY,WAAW,UAAU;CAExE,OACE,oBAAC,aAAD;EACU;EACR,UAAU,MAAM;EACT;EACP,QAAQ;GACN,MAAM;GACN,UAAU;GACV,uBAAuB,MAAM;GAC7B,uBAAuB,MAAM;GAC7B,UAAU;GACV,MAAM;EACR;CACD,CAAA;AAEL"}
|
|
@@ -1,32 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CopyableText } from "../../../ui/copyable-text.js";
|
|
3
|
-
import { formatCell } from "../../lib/format.js";
|
|
4
|
-
import { numericValue } from "../../../format/numeric.js";
|
|
5
|
-
import { formatNumber } from "../../../format/number.js";
|
|
1
|
+
import { NumericCell } from "./numeric-cell.js";
|
|
6
2
|
import { jsx } from "react/jsx-runtime";
|
|
7
3
|
//#region resources/js/table/components/cells/number-cell.tsx
|
|
8
|
-
var NumberCell = ({ column, props, value }) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
22
|
-
if (!props.copyable) return content;
|
|
23
|
-
return /* @__PURE__ */ jsx(CopyableText, {
|
|
24
|
-
value: String(value),
|
|
25
|
-
label: column.props.label ?? column.key,
|
|
26
|
-
testId: `copy-${column.key}`,
|
|
27
|
-
children: content
|
|
28
|
-
});
|
|
29
|
-
};
|
|
4
|
+
var NumberCell = ({ column, props, value }) => /* @__PURE__ */ jsx(NumericCell, {
|
|
5
|
+
column,
|
|
6
|
+
copyable: props.copyable,
|
|
7
|
+
value,
|
|
8
|
+
format: {
|
|
9
|
+
kind: "number",
|
|
10
|
+
notation: props.compact ? "compact" : "standard",
|
|
11
|
+
minimumFractionDigits: props.minimumFractionDigits,
|
|
12
|
+
maximumFractionDigits: props.maximumFractionDigits,
|
|
13
|
+
currency: null,
|
|
14
|
+
unit: props.unit
|
|
15
|
+
}
|
|
16
|
+
});
|
|
30
17
|
//#endregion
|
|
31
18
|
export { NumberCell };
|
|
32
19
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/number-cell.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"number-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/number-cell.tsx"],"sourcesContent":["import type { ColumnCellComponent } from \"@lattice-php/lattice/table/registry\";\nimport { NumericCell } from \"./numeric-cell\";\n\nexport const NumberCell: ColumnCellComponent<\"column.number\"> = ({ column, props, value }) => (\n <NumericCell\n column={column}\n copyable={props.copyable}\n value={value}\n format={{\n kind: \"number\",\n notation: props.compact ? \"compact\" : \"standard\",\n minimumFractionDigits: props.minimumFractionDigits,\n maximumFractionDigits: props.maximumFractionDigits,\n currency: null,\n unit: props.unit,\n }}\n />\n);\n"],"mappings":";;;AAGA,IAAa,cAAoD,EAAE,QAAQ,OAAO,YAChF,oBAAC,aAAD;CACU;CACR,UAAU,MAAM;CACT;CACP,QAAQ;EACN,MAAM;EACN,UAAU,MAAM,UAAU,YAAY;EACtC,uBAAuB,MAAM;EAC7B,uBAAuB,MAAM;EAC7B,UAAU;EACV,MAAM,MAAM;CACd;AACD,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { NumberFormat } from '../../../types/generated.js';
|
|
3
|
+
import { TableColumn } from '../../types.js';
|
|
4
|
+
/** Shared numeric cell body for the money and number columns. */
|
|
5
|
+
export declare function NumericCell({ column, copyable, format, value, }: {
|
|
6
|
+
column: TableColumn;
|
|
7
|
+
copyable?: boolean | null;
|
|
8
|
+
format: NumberFormat;
|
|
9
|
+
value: unknown;
|
|
10
|
+
}): ReactNode;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useLocale } from "../../../i18n/locale.js";
|
|
2
|
+
import { formatCell } from "../../lib/format.js";
|
|
3
|
+
import { numericValue } from "../../../format/numeric.js";
|
|
4
|
+
import { formatNumber } from "../../../format/number.js";
|
|
5
|
+
import { CopyableCell } from "./copyable-cell.js";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
//#region resources/js/table/components/cells/numeric-cell.tsx
|
|
8
|
+
/** Shared numeric cell body for the money and number columns. */
|
|
9
|
+
function NumericCell({ column, copyable, format, value }) {
|
|
10
|
+
const { locale } = useLocale();
|
|
11
|
+
if (numericValue(value) === null) return /* @__PURE__ */ jsx("span", { children: formatCell(value, column) });
|
|
12
|
+
return /* @__PURE__ */ jsx(CopyableCell, {
|
|
13
|
+
column,
|
|
14
|
+
copyable,
|
|
15
|
+
value: String(value),
|
|
16
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
17
|
+
className: "tabular-nums",
|
|
18
|
+
children: formatNumber(value, format, locale)
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { NumericCell };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=numeric-cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numeric-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/numeric-cell.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"@lattice-php/lattice/i18n\";\nimport type { NumberFormat } from \"@lattice-php/lattice/types/generated\";\nimport { formatNumber } from \"@lattice-php/lattice/format/number\";\nimport { numericValue } from \"@lattice-php/lattice/format/numeric\";\nimport { formatCell } from \"@lattice-php/lattice/table/lib/format\";\nimport type { TableColumn } from \"@lattice-php/lattice/table/types\";\nimport { CopyableCell } from \"./copyable-cell\";\n\n/** Shared numeric cell body for the money and number columns. */\nexport function NumericCell({\n column,\n copyable,\n format,\n value,\n}: {\n column: TableColumn;\n copyable?: boolean | null;\n format: NumberFormat;\n value: unknown;\n}): ReactNode {\n const { locale } = useLocale();\n\n if (numericValue(value) === null) {\n return <span>{formatCell(value, column)}</span>;\n }\n\n return (\n <CopyableCell column={column} copyable={copyable} value={String(value)}>\n <span className=\"tabular-nums\">{formatNumber(value, format, locale)}</span>\n </CopyableCell>\n );\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,YAAY,EAC1B,QACA,UACA,QACA,SAMY;CACZ,MAAM,EAAE,WAAW,UAAU;CAE7B,IAAI,aAAa,KAAK,MAAM,MAC1B,OAAO,oBAAC,QAAD,EAAA,UAAO,WAAW,OAAO,MAAM,EAAQ,CAAA;CAGhD,OACE,oBAAC,cAAD;EAAsB;EAAkB;EAAU,OAAO,OAAO,KAAK;YACnE,oBAAC,QAAD;GAAM,WAAU;aAAgB,aAAa,OAAO,QAAQ,MAAM;EAAQ,CAAA;CAC9D,CAAA;AAElB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Renderer } from "../../../core/renderer.js";
|
|
2
1
|
import { materializeSchema } from "../../../core/materialize.js";
|
|
2
|
+
import { Renderer } from "../../../core/renderer.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
//#region resources/js/table/components/cells/stack-cell.tsx
|
|
5
5
|
var StackCell = ({ column, row }) => /* @__PURE__ */ jsx("div", {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { DateTime } from "../../../i18n/date-time.js";
|
|
3
|
-
import { CopyableText } from "../../../ui/copyable-text.js";
|
|
4
3
|
import { coerceColor, namedColor, toneProps } from "../../../lib/color.js";
|
|
5
4
|
import { formatCell, resolveLink } from "../../lib/format.js";
|
|
5
|
+
import { CopyableCell } from "./copyable-cell.js";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
//#region resources/js/table/components/cells/text-cell.tsx
|
|
8
8
|
var TextCell = (args) => {
|
|
@@ -57,11 +57,10 @@ function PlainTextCell({ column, props, row, value }) {
|
|
|
57
57
|
dateStyle: dateProps.dateStyle,
|
|
58
58
|
timeStyle: dateProps.timeStyle
|
|
59
59
|
});
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
return /* @__PURE__ */ jsx(CopyableCell, {
|
|
61
|
+
column,
|
|
62
|
+
copyable: props.copyable,
|
|
62
63
|
value: text,
|
|
63
|
-
label: column.props.label ?? column.key,
|
|
64
|
-
testId: `copy-${column.key}`,
|
|
65
64
|
children: content
|
|
66
65
|
});
|
|
67
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/text-cell.tsx"],"sourcesContent":["import { DateTime } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { coerceColor, namedColor, toneProps } from \"@lattice-php/lattice/lib/color\";\nimport
|
|
1
|
+
{"version":3,"file":"text-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/text-cell.tsx"],"sourcesContent":["import { DateTime } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { coerceColor, namedColor, toneProps } from \"@lattice-php/lattice/lib/color\";\nimport type { ReactNode } from \"react\";\nimport { formatCell, resolveLink } from \"@lattice-php/lattice/table/lib/format\";\nimport type { ColumnCellArgs, ColumnCellComponent } from \"@lattice-php/lattice/table/registry\";\nimport type { ColumnPropsOf } from \"@lattice-php/lattice/table/types\";\nimport { CopyableCell } from \"./copyable-cell\";\n\ntype TextProps = ColumnCellArgs<\"column.text\">[\"props\"];\n\nexport const TextCell: ColumnCellComponent<\"column.text\"> = (args) => {\n if (args.props.multiple) {\n return <MultipleCell {...args} />;\n }\n\n if (args.props.badge) {\n return <SingleBadgeCell {...args} />;\n }\n\n return <PlainTextCell {...args} />;\n};\n\nfunction Badge({ label, color }: { label: string; color?: string | null }): ReactNode {\n if (label === \"\") {\n return null;\n }\n\n const tone = toneProps(coerceColor(color) ?? namedColor(\"gray\"));\n\n return (\n <span className={cn(\"lt-cell-badge\", tone.className)} style={tone.style}>\n {label}\n </span>\n );\n}\n\nfunction MultipleCell({ column, props, value }: ColumnCellArgs<\"column.text\">): ReactNode {\n const items = Array.isArray(value) ? value : [];\n\n if (items.length === 0) {\n return null;\n }\n\n if (!props.badge) {\n return <span>{items.map((item) => formatCell(item, column)).join(\", \")}</span>;\n }\n\n return (\n <div className=\"flex flex-wrap gap-1\">\n {items.map((item, index) => {\n const chip = item as { value: unknown; color?: string };\n\n return <Badge key={index} label={formatCell(chip.value, column)} color={chip.color} />;\n })}\n </div>\n );\n}\n\nfunction SingleBadgeCell({ column, props, row, value }: ColumnCellArgs<\"column.text\">): ReactNode {\n const colorKey = (props.badge as NonNullable<TextProps[\"badge\"]>).colorKey;\n\n return <Badge label={formatCell(value, column)} color={String(row[colorKey] ?? \"\")} />;\n}\n\nfunction PlainTextCell({ column, props, row, value }: ColumnCellArgs<\"column.text\">): ReactNode {\n const dateProps = (column.props as ColumnPropsOf<\"column.text\">).date;\n const href = resolveLink(column, row, value);\n const text = formatCell(value, column);\n\n const content = href ? (\n <a\n className=\"underline underline-offset-2\"\n href={href}\n rel={props.link?.external ? \"noreferrer\" : undefined}\n target={props.link?.external ? \"_blank\" : undefined}\n >\n {text}\n </a>\n ) : (\n text\n );\n\n if (dateProps && !href && !props.copyable && value !== null && value !== undefined) {\n return (\n <DateTime value={value} dateStyle={dateProps.dateStyle} timeStyle={dateProps.timeStyle} />\n );\n }\n\n return (\n <CopyableCell column={column} copyable={props.copyable} value={text}>\n {content}\n </CopyableCell>\n );\n}\n"],"mappings":";;;;;;;AAWA,IAAa,YAAgD,SAAS;CACpE,IAAI,KAAK,MAAM,UACb,OAAO,oBAAC,cAAD,EAAc,GAAI,KAAO,CAAA;CAGlC,IAAI,KAAK,MAAM,OACb,OAAO,oBAAC,iBAAD,EAAiB,GAAI,KAAO,CAAA;CAGrC,OAAO,oBAAC,eAAD,EAAe,GAAI,KAAO,CAAA;AACnC;AAEA,SAAS,MAAM,EAAE,OAAO,SAA8D;CACpF,IAAI,UAAU,IACZ,OAAO;CAGT,MAAM,OAAO,UAAU,YAAY,KAAK,KAAK,WAAW,MAAM,CAAC;CAE/D,OACE,oBAAC,QAAD;EAAM,WAAW,GAAG,iBAAiB,KAAK,SAAS;EAAG,OAAO,KAAK;YAC/D;CACG,CAAA;AAEV;AAEA,SAAS,aAAa,EAAE,QAAQ,OAAO,SAAmD;CACxF,MAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;CAE9C,IAAI,MAAM,WAAW,GACnB,OAAO;CAGT,IAAI,CAAC,MAAM,OACT,OAAO,oBAAC,QAAD,EAAA,UAAO,MAAM,KAAK,SAAS,WAAW,MAAM,MAAM,CAAC,EAAE,KAAK,IAAI,EAAQ,CAAA;CAG/E,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,MAAM,KAAK,MAAM,UAAU;GAC1B,MAAM,OAAO;GAEb,OAAO,oBAAC,OAAD;IAAmB,OAAO,WAAW,KAAK,OAAO,MAAM;IAAG,OAAO,KAAK;GAAQ,GAAlE,KAAkE;EACvF,CAAC;CACE,CAAA;AAET;AAEA,SAAS,gBAAgB,EAAE,QAAQ,OAAO,KAAK,SAAmD;CAChG,MAAM,WAAY,MAAM,MAA0C;CAElE,OAAO,oBAAC,OAAD;EAAO,OAAO,WAAW,OAAO,MAAM;EAAG,OAAO,OAAO,IAAI,aAAa,EAAE;CAAI,CAAA;AACvF;AAEA,SAAS,cAAc,EAAE,QAAQ,OAAO,KAAK,SAAmD;CAC9F,MAAM,YAAa,OAAO,MAAuC;CACjE,MAAM,OAAO,YAAY,QAAQ,KAAK,KAAK;CAC3C,MAAM,OAAO,WAAW,OAAO,MAAM;CAErC,MAAM,UAAU,OACd,oBAAC,KAAD;EACE,WAAU;EACJ;EACN,KAAK,MAAM,MAAM,WAAW,eAAe,KAAA;EAC3C,QAAQ,MAAM,MAAM,WAAW,WAAW,KAAA;YAEzC;CACA,CAAA,IAEH;CAGF,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,YAAY,UAAU,QAAQ,UAAU,KAAA,GACvE,OACE,oBAAC,UAAD;EAAiB;EAAO,WAAW,UAAU;EAAW,WAAW,UAAU;CAAY,CAAA;CAI7F,OACE,oBAAC,cAAD;EAAsB;EAAQ,UAAU,MAAM;EAAU,OAAO;YAC5D;CACW,CAAA;AAElB"}
|
|
@@ -11,6 +11,7 @@ import { TableCellProvider } from "../../form/hooks/row-layout-context.js";
|
|
|
11
11
|
import { Checkbox } from "../../ui/checkbox.js";
|
|
12
12
|
import { IconButton } from "../../ui/icon-button.js";
|
|
13
13
|
import { filterValue, isActiveFilterValue } from "../lib/filter-values.js";
|
|
14
|
+
import { isTruthy } from "../../lib/is-truthy.js";
|
|
14
15
|
import { useCallback, useMemo, useRef } from "react";
|
|
15
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
17
|
//#region resources/js/table/components/filter-controls.tsx
|
|
@@ -120,9 +121,6 @@ function ToggleControl({ filter, value, processing, onChange }) {
|
|
|
120
121
|
}), /* @__PURE__ */ jsx("span", { children: filter.props.label })]
|
|
121
122
|
});
|
|
122
123
|
}
|
|
123
|
-
function isTruthy(value) {
|
|
124
|
-
return value === true || value === "1" || value === 1 || value === "true";
|
|
125
|
-
}
|
|
126
124
|
//#endregion
|
|
127
125
|
export { TableFilterControl };
|
|
128
126
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { useCallback, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, Option } from \"@lattice-php/lattice/core/types\";\nimport {\n FieldCommitOverrideProvider,\n FormProvider,\n FormValuesProvider,\n getPath,\n PrefillProvider,\n ResolvedNodesProvider,\n setPath,\n TableCellProvider,\n useFormValues,\n useSetFormValue,\n} from \"@lattice-php/lattice/form/embed\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { filterValue, isActiveFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport type { FilterNode } from \"@lattice-php/lattice/table/types\";\n\nexport type FilterOptionSearch = (\n field: string,\n query: string,\n signal: AbortSignal,\n) => Promise<Option[]>;\n\ntype FilterValue = Record<string, unknown>;\n\nexport function TableFilterControl({\n filter,\n value,\n processing,\n bare = false,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n bare?: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const schema = filter.schema ?? [];\n\n if (schema.length === 0) {\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n }\n\n return (\n <div className=\"flex items-end gap-2\">\n <div className=\"min-w-0 flex-1\">\n <SchemaControl\n filter={filter}\n schema={schema}\n value={value}\n processing={processing}\n bare={bare}\n onChange={onChange}\n onSearch={onSearch}\n />\n </div>\n {isActiveFilterValue(value) && (\n <IconButton\n size=\"md\"\n icon=\"x\"\n label={t(\"table.filter.clear\", \"Clear {{label}} filter\", {\n label: filter.props.label ?? \"\",\n })}\n disabled={processing}\n onClick={() => onChange(undefined)}\n />\n )}\n </div>\n );\n}\n\nfunction SchemaControl({\n filter,\n schema,\n value,\n processing,\n bare,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n schema: Node[];\n value: unknown;\n processing: boolean;\n bare: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const initial = useMemo(() => filterValue(value), [value]);\n const form = useMemo(\n () => ({\n action: \"#\",\n clearErrors: () => {},\n componentId: `table-filter-${filter.key}`,\n componentRef: \"\",\n errors: {},\n fieldIdPrefix: `table-filter-${filter.key}`,\n fieldLabels: {},\n precognitive: false,\n processing,\n searchOptions: (\n field: string,\n query: string,\n _values: Record<string, unknown>,\n signal: AbortSignal,\n ) => (onSearch ? onSearch(field, query, signal) : Promise.resolve([])),\n validate: () => {},\n }),\n [filter.key, onSearch, processing],\n );\n\n const content = (\n <div\n aria-disabled={processing}\n className={cn(\"grid gap-3\", processing && \"pointer-events-none opacity-60\")}\n >\n <Renderer nodes={schema} />\n </div>\n );\n\n return (\n <FormProvider value={form}>\n <PrefillProvider value={{ markUserEdit: () => {} }}>\n <ResolvedNodesProvider nodes={{}}>\n <FormValuesProvider initial={initial}>\n <TableFilterCommitBridge onChange={onChange}>\n {bare ? <TableCellProvider>{content}</TableCellProvider> : content}\n </TableFilterCommitBridge>\n </FormValuesProvider>\n </ResolvedNodesProvider>\n </PrefillProvider>\n </FormProvider>\n );\n}\n\nfunction TableFilterCommitBridge({\n children,\n onChange,\n}: {\n children: ReactNode;\n onChange: (value: FilterValue) => void;\n}) {\n const values = useFormValues();\n const setValue = useSetFormValue();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n\n const write = useCallback(\n (name: string, value: unknown) => {\n const nextValue =\n typeof value === \"function\"\n ? (value as (previous: unknown) => unknown)(getPath(valuesRef.current, name))\n : value;\n const next = setPath(valuesRef.current, name, nextValue);\n\n valuesRef.current = next;\n setValue(name, nextValue);\n onChange(next);\n },\n [onChange, setValue],\n );\n\n const commit = useMemo(\n () => ({\n blur: () => {},\n change: write,\n commit: write,\n }),\n [write],\n );\n\n return <FieldCommitOverrideProvider value={commit}>{children}</FieldCommitOverrideProvider>;\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = isTruthy(filterValue(value).value);\n\n return (\n <label className=\"flex h-lt-control-md cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.props.label ?? undefined}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? { value: \"1\" } : undefined)}\n />\n <span>{filter.props.label}</span>\n </label>\n );\n}\n
|
|
1
|
+
{"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { useCallback, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, Option } from \"@lattice-php/lattice/core/types\";\nimport {\n FieldCommitOverrideProvider,\n FormProvider,\n FormValuesProvider,\n getPath,\n PrefillProvider,\n ResolvedNodesProvider,\n setPath,\n TableCellProvider,\n useFormValues,\n useSetFormValue,\n} from \"@lattice-php/lattice/form/embed\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { isTruthy } from \"@lattice-php/lattice/lib/is-truthy\";\nimport { filterValue, isActiveFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport type { FilterNode } from \"@lattice-php/lattice/table/types\";\n\nexport type FilterOptionSearch = (\n field: string,\n query: string,\n signal: AbortSignal,\n) => Promise<Option[]>;\n\ntype FilterValue = Record<string, unknown>;\n\nexport function TableFilterControl({\n filter,\n value,\n processing,\n bare = false,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n bare?: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const schema = filter.schema ?? [];\n\n if (schema.length === 0) {\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n }\n\n return (\n <div className=\"flex items-end gap-2\">\n <div className=\"min-w-0 flex-1\">\n <SchemaControl\n filter={filter}\n schema={schema}\n value={value}\n processing={processing}\n bare={bare}\n onChange={onChange}\n onSearch={onSearch}\n />\n </div>\n {isActiveFilterValue(value) && (\n <IconButton\n size=\"md\"\n icon=\"x\"\n label={t(\"table.filter.clear\", \"Clear {{label}} filter\", {\n label: filter.props.label ?? \"\",\n })}\n disabled={processing}\n onClick={() => onChange(undefined)}\n />\n )}\n </div>\n );\n}\n\nfunction SchemaControl({\n filter,\n schema,\n value,\n processing,\n bare,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n schema: Node[];\n value: unknown;\n processing: boolean;\n bare: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const initial = useMemo(() => filterValue(value), [value]);\n const form = useMemo(\n () => ({\n action: \"#\",\n clearErrors: () => {},\n componentId: `table-filter-${filter.key}`,\n componentRef: \"\",\n errors: {},\n fieldIdPrefix: `table-filter-${filter.key}`,\n fieldLabels: {},\n precognitive: false,\n processing,\n searchOptions: (\n field: string,\n query: string,\n _values: Record<string, unknown>,\n signal: AbortSignal,\n ) => (onSearch ? onSearch(field, query, signal) : Promise.resolve([])),\n validate: () => {},\n }),\n [filter.key, onSearch, processing],\n );\n\n const content = (\n <div\n aria-disabled={processing}\n className={cn(\"grid gap-3\", processing && \"pointer-events-none opacity-60\")}\n >\n <Renderer nodes={schema} />\n </div>\n );\n\n return (\n <FormProvider value={form}>\n <PrefillProvider value={{ markUserEdit: () => {} }}>\n <ResolvedNodesProvider nodes={{}}>\n <FormValuesProvider initial={initial}>\n <TableFilterCommitBridge onChange={onChange}>\n {bare ? <TableCellProvider>{content}</TableCellProvider> : content}\n </TableFilterCommitBridge>\n </FormValuesProvider>\n </ResolvedNodesProvider>\n </PrefillProvider>\n </FormProvider>\n );\n}\n\nfunction TableFilterCommitBridge({\n children,\n onChange,\n}: {\n children: ReactNode;\n onChange: (value: FilterValue) => void;\n}) {\n const values = useFormValues();\n const setValue = useSetFormValue();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n\n const write = useCallback(\n (name: string, value: unknown) => {\n const nextValue =\n typeof value === \"function\"\n ? (value as (previous: unknown) => unknown)(getPath(valuesRef.current, name))\n : value;\n const next = setPath(valuesRef.current, name, nextValue);\n\n valuesRef.current = next;\n setValue(name, nextValue);\n onChange(next);\n },\n [onChange, setValue],\n );\n\n const commit = useMemo(\n () => ({\n blur: () => {},\n change: write,\n commit: write,\n }),\n [write],\n );\n\n return <FieldCommitOverrideProvider value={commit}>{children}</FieldCommitOverrideProvider>;\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = isTruthy(filterValue(value).value);\n\n return (\n <label className=\"flex h-lt-control-md cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.props.label ?? undefined}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? { value: \"1\" } : undefined)}\n />\n <span>{filter.props.label}</span>\n </label>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,SAAgB,mBAAmB,EACjC,QACA,OACA,YACA,OAAO,OACP,UACA,YAQC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,SAAS,OAAO,UAAU,CAAC;CAEjC,IAAI,OAAO,WAAW,GACpB,OACE,oBAAC,eAAD;EAAuB;EAAe;EAAmB;EAAsB;CAAW,CAAA;CAI9F,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,eAAD;IACU;IACA;IACD;IACK;IACN;IACI;IACA;GACX,CAAA;EACE,CAAA,GACJ,oBAAoB,KAAK,KACxB,oBAAC,YAAD;GACE,MAAK;GACL,MAAK;GACL,OAAO,EAAE,sBAAsB,0BAA0B,EACvD,OAAO,OAAO,MAAM,SAAS,GAC/B,CAAC;GACD,UAAU;GACV,eAAe,SAAS,KAAA,CAAS;EAClC,CAAA,CAEA;;AAET;AAEA,SAAS,cAAc,EACrB,QACA,QACA,OACA,YACA,MACA,UACA,YASC;CACD,MAAM,UAAU,cAAc,YAAY,KAAK,GAAG,CAAC,KAAK,CAAC;CACzD,MAAM,OAAO,eACJ;EACL,QAAQ;EACR,mBAAmB,CAAC;EACpB,aAAa,gBAAgB,OAAO;EACpC,cAAc;EACd,QAAQ,CAAC;EACT,eAAe,gBAAgB,OAAO;EACtC,aAAa,CAAC;EACd,cAAc;EACd;EACA,gBACE,OACA,OACA,SACA,WACI,WAAW,SAAS,OAAO,OAAO,MAAM,IAAI,QAAQ,QAAQ,CAAC,CAAC;EACpE,gBAAgB,CAAC;CACnB,IACA;EAAC,OAAO;EAAK;EAAU;CAAU,CACnC;CAEA,MAAM,UACJ,oBAAC,OAAD;EACE,iBAAe;EACf,WAAW,GAAG,cAAc,cAAc,gCAAgC;YAE1E,oBAAC,UAAD,EAAU,OAAO,OAAS,CAAA;CACvB,CAAA;CAGP,OACE,oBAAC,cAAD;EAAc,OAAO;YACnB,oBAAC,iBAAD;GAAiB,OAAO,EAAE,oBAAoB,CAAC,EAAE;aAC/C,oBAAC,uBAAD;IAAuB,OAAO,CAAC;cAC7B,oBAAC,oBAAD;KAA6B;eAC3B,oBAAC,yBAAD;MAAmC;gBAChC,OAAO,oBAAC,mBAAD,EAAA,UAAoB,QAA2B,CAAA,IAAI;KACpC,CAAA;IACP,CAAA;GACC,CAAA;EACR,CAAA;CACL,CAAA;AAElB;AAEA,SAAS,wBAAwB,EAC/B,UACA,YAIC;CACD,MAAM,SAAS,cAAc;CAC7B,MAAM,WAAW,gBAAgB;CACjC,MAAM,YAAY,OAAO,MAAM;CAC/B,UAAU,UAAU;CAEpB,MAAM,QAAQ,aACX,MAAc,UAAmB;EAChC,MAAM,YACJ,OAAO,UAAU,aACZ,MAAyC,QAAQ,UAAU,SAAS,IAAI,CAAC,IAC1E;EACN,MAAM,OAAO,QAAQ,UAAU,SAAS,MAAM,SAAS;EAEvD,UAAU,UAAU;EACpB,SAAS,MAAM,SAAS;EACxB,SAAS,IAAI;CACf,GACA,CAAC,UAAU,QAAQ,CACrB;CAWA,OAAO,oBAAC,6BAAD;EAA6B,OATrB,eACN;GACL,YAAY,CAAC;GACb,QAAQ;GACR,QAAQ;EACV,IACA,CAAC,KAAK,CAGmC;EAAS;CAAsC,CAAA;AAC5F;AAEA,SAAS,cAAc,EACrB,QACA,OACA,YACA,YAMC;CACD,MAAM,UAAU,SAAS,YAAY,KAAK,EAAE,KAAK;CAEjD,OACE,qBAAC,SAAD;EAAO,WAAU;YAAjB,CACE,oBAAC,UAAD;GACE,cAAY,OAAO,MAAM,SAAS,KAAA;GAClC,aAAW,gBAAgB,OAAO;GACzB;GACT,UAAU;GACV,kBAAkB,SAAS,SAAS,SAAS,OAAO,EAAE,OAAO,IAAI,IAAI,KAAA,CAAS;EAC/E,CAAA,GACD,oBAAC,QAAD,EAAA,UAAO,OAAO,MAAM,MAAY,CAAA,CAC3B;;AAEX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-cell.js","names":[],"sources":["../../../resources/js/table/components/table-cell.tsx"],"sourcesContent":["import { useColumnRegistry } from \"@lattice-php/lattice/core/registry-context\";\nimport type {
|
|
1
|
+
{"version":3,"file":"table-cell.js","names":[],"sources":["../../../resources/js/table/components/table-cell.tsx"],"sourcesContent":["import { useColumnRegistry } from \"@lattice-php/lattice/core/registry-context\";\nimport type { ColumnNodeType } from \"@lattice-php/lattice/types/generated\";\nimport {\n columnCell,\n type ColumnRegistry,\n type ColumnRegistryFor,\n} from \"@lattice-php/lattice/table/registry\";\nimport type { TableColumn, TableRow } from \"@lattice-php/lattice/table/types\";\nimport { BadgeCell } from \"./cells/badge-cell\";\nimport { BooleanCell } from \"./cells/boolean-cell\";\nimport { IconCell } from \"./cells/icon-cell\";\nimport { ImageCell } from \"./cells/image-cell\";\nimport { MoneyCell } from \"./cells/money-cell\";\nimport { NumberCell } from \"./cells/number-cell\";\nimport { StackCell } from \"./cells/stack-cell\";\nimport { TextCell } from \"./cells/text-cell\";\n\n// Built-in cells live with the (lazy-loaded) table feature rather than the\n// eager registry, so they stay code-split. Consumer-registered columns are\n// merged on top and win on type collisions.\nconst builtinColumnCells: ColumnRegistry = {\n \"column.badge\": columnCell(BadgeCell),\n \"column.boolean\": columnCell(BooleanCell),\n \"column.icon\": columnCell(IconCell),\n \"column.image\": columnCell(ImageCell),\n \"column.money\": columnCell(MoneyCell),\n \"column.number\": columnCell(NumberCell),\n \"column.stack\": columnCell(StackCell),\n \"column.text\": columnCell(TextCell),\n} satisfies ColumnRegistryFor<ColumnNodeType>;\n\nexport function ColumnCell({ column, row }: { column: TableColumn; row: TableRow }) {\n const customCells = useColumnRegistry();\n const Cell =\n customCells[column.type] ??\n builtinColumnCells[column.type] ??\n builtinColumnCells[\"column.text\"];\n\n return <Cell column={column} props={column.props} row={row} value={row[column.key]} />;\n}\n"],"mappings":";;;;;;;;;;;;AAoBA,IAAM,qBAAqC;CACzC,gBAAgB,WAAW,SAAS;CACpC,kBAAkB,WAAW,WAAW;CACxC,eAAe,WAAW,QAAQ;CAClC,gBAAgB,WAAW,SAAS;CACpC,gBAAgB,WAAW,SAAS;CACpC,iBAAiB,WAAW,UAAU;CACtC,gBAAgB,WAAW,SAAS;CACpC,eAAe,WAAW,QAAQ;AACpC;AAEA,SAAgB,WAAW,EAAE,QAAQ,OAA+C;CAOlF,OAAO,oBANa,kBAElB,EAAY,OAAO,SACnB,mBAAmB,OAAO,SAC1B,mBAAmB,gBAEd;EAAc;EAAQ,OAAO,OAAO;EAAY;EAAK,OAAO,IAAI,OAAO;CAAO,CAAA;AACvF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cn } from "../../lib/utils.js";
|
|
2
2
|
import { Icon } from "../../icons/sprite.js";
|
|
3
3
|
import { useT } from "../../i18n/instance.js";
|
|
4
|
+
import { useDebouncedCallback } from "../../lib/use-debounced-callback.js";
|
|
4
5
|
import { Input } from "../../ui/input.js";
|
|
5
6
|
import { IconButton } from "../../ui/icon-button.js";
|
|
6
7
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -15,7 +16,6 @@ var DEBOUNCE_MS = 300;
|
|
|
15
16
|
function TableSearch({ value, onSearch }) {
|
|
16
17
|
const { t } = useT("lattice");
|
|
17
18
|
const [term, setTerm] = useState(value);
|
|
18
|
-
const timer = useRef(null);
|
|
19
19
|
const committed = useRef(value);
|
|
20
20
|
useEffect(() => {
|
|
21
21
|
if (value !== committed.current) {
|
|
@@ -23,20 +23,17 @@ function TableSearch({ value, onSearch }) {
|
|
|
23
23
|
setTerm(value);
|
|
24
24
|
}
|
|
25
25
|
}, [value]);
|
|
26
|
-
useEffect(() => () => {
|
|
27
|
-
if (timer.current) clearTimeout(timer.current);
|
|
28
|
-
}, []);
|
|
29
26
|
function commit(next) {
|
|
30
27
|
committed.current = next;
|
|
31
28
|
onSearch(next);
|
|
32
29
|
}
|
|
30
|
+
const commitDebounced = useDebouncedCallback(commit, DEBOUNCE_MS);
|
|
33
31
|
function change(next) {
|
|
34
32
|
setTerm(next);
|
|
35
|
-
|
|
36
|
-
timer.current = setTimeout(() => commit(next), DEBOUNCE_MS);
|
|
33
|
+
commitDebounced(next);
|
|
37
34
|
}
|
|
38
35
|
function clear() {
|
|
39
|
-
|
|
36
|
+
commitDebounced.cancel();
|
|
40
37
|
setTerm("");
|
|
41
38
|
commit("");
|
|
42
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-search.js","names":[],"sources":["../../../resources/js/table/components/table-search.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { Input } from \"@lattice-php/lattice/ui/input\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\nconst DEBOUNCE_MS = 300;\n\n/**\n * The table-level quick-search box. Keystrokes update the input immediately and\n * commit the term to the server after a short debounce; an externally-changed\n * value (e.g. a filter reset) is adopted without echoing keystroke round-trips.\n */\nexport function TableSearch({\n value,\n onSearch,\n}: {\n value: string;\n onSearch: (term: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n const [term, setTerm] = useState(value);\n const
|
|
1
|
+
{"version":3,"file":"table-search.js","names":[],"sources":["../../../resources/js/table/components/table-search.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { Input } from \"@lattice-php/lattice/ui/input\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useDebouncedCallback } from \"@lattice-php/lattice/lib/use-debounced-callback\";\n\nconst DEBOUNCE_MS = 300;\n\n/**\n * The table-level quick-search box. Keystrokes update the input immediately and\n * commit the term to the server after a short debounce; an externally-changed\n * value (e.g. a filter reset) is adopted without echoing keystroke round-trips.\n */\nexport function TableSearch({\n value,\n onSearch,\n}: {\n value: string;\n onSearch: (term: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n const [term, setTerm] = useState(value);\n const committed = useRef(value);\n\n useEffect(() => {\n if (value !== committed.current) {\n committed.current = value;\n setTerm(value);\n }\n }, [value]);\n\n function commit(next: string): void {\n committed.current = next;\n onSearch(next);\n }\n\n const commitDebounced = useDebouncedCallback(commit, DEBOUNCE_MS);\n\n function change(next: string): void {\n setTerm(next);\n commitDebounced(next);\n }\n\n function clear(): void {\n commitDebounced.cancel();\n setTerm(\"\");\n commit(\"\");\n }\n\n const label = t(\"table.search.placeholder\", \"Search\");\n\n return (\n <div className=\"relative w-full max-w-xs\">\n <Icon\n name=\"search\"\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-2.5 top-1/2 size-lt-icon-sm -translate-y-1/2 text-lt-muted-fg\"\n />\n <Input\n type=\"search\"\n data-test=\"table-search\"\n value={term}\n placeholder={label}\n aria-label={label}\n onChange={(event) => change(event.target.value)}\n className={cn(\"px-8\", \"[&::-webkit-search-cancel-button]:hidden\")}\n />\n {term !== \"\" && (\n <IconButton\n size=\"xs\"\n icon=\"x\"\n label={t(\"table.search.clear\", \"Clear search\")}\n data-test=\"table-search-clear\"\n className=\"absolute right-1.5 top-1/2 -translate-y-1/2\"\n onClick={clear}\n />\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAQA,IAAM,cAAc;;;;;;AAOpB,SAAgB,YAAY,EAC1B,OACA,YAIC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,YAAY,OAAO,KAAK;CAE9B,gBAAgB;EACd,IAAI,UAAU,UAAU,SAAS;GAC/B,UAAU,UAAU;GACpB,QAAQ,KAAK;EACf;CACF,GAAG,CAAC,KAAK,CAAC;CAEV,SAAS,OAAO,MAAoB;EAClC,UAAU,UAAU;EACpB,SAAS,IAAI;CACf;CAEA,MAAM,kBAAkB,qBAAqB,QAAQ,WAAW;CAEhE,SAAS,OAAO,MAAoB;EAClC,QAAQ,IAAI;EACZ,gBAAgB,IAAI;CACtB;CAEA,SAAS,QAAc;EACrB,gBAAgB,OAAO;EACvB,QAAQ,EAAE;EACV,OAAO,EAAE;CACX;CAEA,MAAM,QAAQ,EAAE,4BAA4B,QAAQ;CAEpD,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,oBAAC,MAAD;IACE,MAAK;IACL,eAAY;IACZ,WAAU;GACX,CAAA;GACD,oBAAC,OAAD;IACE,MAAK;IACL,aAAU;IACV,OAAO;IACP,aAAa;IACb,cAAY;IACZ,WAAW,UAAU,OAAO,MAAM,OAAO,KAAK;IAC9C,WAAW,GAAG,QAAQ,0CAA0C;GACjE,CAAA;GACA,SAAS,MACR,oBAAC,YAAD;IACE,MAAK;IACL,MAAK;IACL,OAAO,EAAE,sBAAsB,cAAc;IAC7C,aAAU;IACV,WAAU;IACV,SAAS;GACV,CAAA;EAEA;;AAET"}
|