@12-apps/ui 6.2.0 → 6.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-35VGGLOC.js → chunk-CEKPLUQV.js} +2 -2
- package/dist/{chunk-35VGGLOC.js.map → chunk-CEKPLUQV.js.map} +1 -1
- package/dist/{chunk-7XLEWBKL.js → chunk-N554AFDB.js} +7 -10
- package/dist/chunk-N554AFDB.js.map +1 -0
- package/dist/{chunk-JDO7W4D4.js → chunk-R5ZQZSEQ.js} +2 -20
- package/dist/{chunk-JDO7W4D4.js.map → chunk-R5ZQZSEQ.js.map} +1 -1
- package/dist/{chunk-R4TYXKDD.js → chunk-TPQRIPCN.js} +52 -48
- package/dist/chunk-TPQRIPCN.js.map +1 -0
- package/dist/{chunk-62XQWGXU.js → chunk-WFPXRSIZ.js} +20 -18
- package/dist/chunk-WFPXRSIZ.js.map +1 -0
- package/dist/copy.js +1 -0
- package/dist/copy.js.map +1 -0
- package/dist/data-display/CardKit.js +15 -4
- package/dist/data-display/CardKit.js.map +1 -1
- package/dist/data-display/DataViews.js +664 -616
- package/dist/data-display/DataViews.js.map +1 -1
- package/dist/data-display/SectionOnboarding.js +3 -3
- package/dist/data-display/SectionOnboarding.js.map +1 -1
- package/dist/feedback/ConfirmAction.js +3 -5
- package/dist/form/CategorySelect.js +1 -1
- package/dist/form/CepField.js +1 -1
- package/dist/form/total-form.js +8 -4
- package/dist/form/total-form.js.map +1 -1
- package/dist/layout/ContentToolbar.js +1 -1
- package/dist/layout/TableFilter.js +1 -1
- package/dist/pt-BR.js +222 -0
- package/dist/pt-BR.js.map +1 -0
- package/dist/types/components/data-display/CardKit/use-remove-confirm.d.ts +4 -1
- package/dist/types/components/data-display/CardKit/use-remove-confirm.d.ts.map +1 -1
- package/dist/types/components/data-display/CardKit/use-row-confirm.d.ts +5 -2
- package/dist/types/components/data-display/CardKit/use-row-confirm.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/DataViewsBoard.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/DeleteViewDialog.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/ManageViewsDialog.d.ts +4 -1
- package/dist/types/components/data-display/DataViews/ManageViewsDialog.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/SaveViewModal.d.ts +0 -5
- package/dist/types/components/data-display/DataViews/SaveViewModal.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/base-card.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/base-list-card-gutters.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-bar-controls.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-category-pill.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-columns-tab.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-copy-context.d.ts +17 -0
- package/dist/types/components/data-display/DataViews/data-views-copy-context.d.ts.map +1 -0
- package/dist/types/components/data-display/DataViews/data-views-copy.d.ts +205 -0
- package/dist/types/components/data-display/DataViews/data-views-copy.d.ts.map +1 -0
- package/dist/types/components/data-display/DataViews/data-views-display-panel.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-display-tabs.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-export.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-filter-panel.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-grid-helpers.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-more-fields.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-more-filters.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-range-pill.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-range-presets.d.ts +3 -2
- package/dist/types/components/data-display/DataViews/data-views-range-presets.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-scopes.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-search.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-select-all-strip.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-table-parts.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-view-nav.d.ts +1 -1
- package/dist/types/components/data-display/DataViews/data-views-view-nav.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/index.d.ts +2 -0
- package/dist/types/components/data-display/DataViews/index.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/save-view-preview.d.ts +10 -0
- package/dist/types/components/data-display/DataViews/save-view-preview.d.ts.map +1 -0
- package/dist/types/components/data-display/DataViews/use-saved-views-controller.d.ts.map +1 -1
- package/dist/types/components/data-display/SectionOnboarding/SectionOnboarding.types.d.ts +6 -5
- package/dist/types/components/data-display/SectionOnboarding/SectionOnboarding.types.d.ts.map +1 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmAction.hooks.d.ts +1 -3
- package/dist/types/components/feedback/ConfirmAction/ConfirmAction.hooks.d.ts.map +1 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmAction.parts.d.ts +4 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmAction.parts.d.ts.map +1 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmAction.types.d.ts +9 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmAction.types.d.ts.map +1 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmButton.d.ts +2 -1
- package/dist/types/components/feedback/ConfirmAction/ConfirmButton.d.ts.map +1 -1
- package/dist/types/components/feedback/ConfirmAction/index.d.ts +2 -2
- package/dist/types/components/feedback/ConfirmAction/index.d.ts.map +1 -1
- package/dist/types/components/feedback/ConfirmAction/with-confirmation.d.ts +5 -1
- package/dist/types/components/feedback/ConfirmAction/with-confirmation.d.ts.map +1 -1
- package/dist/types/components/form/CategorySelect/CategoryPanel.d.ts +4 -1
- package/dist/types/components/form/CategorySelect/CategoryPanel.d.ts.map +1 -1
- package/dist/types/components/form/CategorySelect/CategoryPanelFoot.d.ts +5 -2
- package/dist/types/components/form/CategorySelect/CategoryPanelFoot.d.ts.map +1 -1
- package/dist/types/components/form/CategorySelect/CategoryPanelHead.d.ts +5 -2
- package/dist/types/components/form/CategorySelect/CategoryPanelHead.d.ts.map +1 -1
- package/dist/types/components/form/CategorySelect/CategoryPanelList.d.ts +3 -0
- package/dist/types/components/form/CategorySelect/CategoryPanelList.d.ts.map +1 -1
- package/dist/types/components/form/CategorySelect/CategorySelect.types.d.ts +5 -0
- package/dist/types/components/form/CategorySelect/CategorySelect.types.d.ts.map +1 -1
- package/dist/types/components/form/CategorySelect/CategoryTrigger.d.ts +4 -1
- package/dist/types/components/form/CategorySelect/CategoryTrigger.d.ts.map +1 -1
- package/dist/types/components/form/CepField/CepField.d.ts +1 -1
- package/dist/types/components/form/CepField/CepField.d.ts.map +1 -1
- package/dist/types/components/form/CepField/CepField.types.d.ts +3 -0
- package/dist/types/components/form/CepField/CepField.types.d.ts.map +1 -1
- package/dist/types/components/form/total-form/Fields/CategoryField.d.ts +4 -1
- package/dist/types/components/form/total-form/Fields/CategoryField.d.ts.map +1 -1
- package/dist/types/components/form/total-form/Fields/CepField.d.ts +4 -1
- package/dist/types/components/form/total-form/Fields/CepField.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts +6 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/SavedViewsMenu.d.ts.map +1 -1
- package/dist/types/copy.d.ts +99 -0
- package/dist/types/copy.d.ts.map +1 -0
- package/dist/types/pt-BR.d.ts +28 -0
- package/dist/types/pt-BR.d.ts.map +1 -0
- package/package.json +10 -2
- package/src/components/data-display/CardKit/use-remove-confirm.tsx +5 -0
- package/src/components/data-display/CardKit/use-row-confirm.tsx +7 -2
- package/src/components/data-display/DataViews/DataViewsBoard.tsx +7 -4
- package/src/components/data-display/DataViews/DeleteViewDialog.tsx +6 -4
- package/src/components/data-display/DataViews/ManageViewsDialog.tsx +26 -10
- package/src/components/data-display/DataViews/SaveViewModal.tsx +56 -90
- package/src/components/data-display/DataViews/base-card.tsx +3 -1
- package/src/components/data-display/DataViews/base-list-card-gutters.tsx +3 -1
- package/src/components/data-display/DataViews/data-views-bar-controls.tsx +8 -5
- package/src/components/data-display/DataViews/data-views-category-pill.tsx +6 -3
- package/src/components/data-display/DataViews/data-views-columns-tab.tsx +5 -3
- package/src/components/data-display/DataViews/data-views-copy-context.tsx +43 -0
- package/src/components/data-display/DataViews/data-views-copy.ts +214 -0
- package/src/components/data-display/DataViews/data-views-display-panel.tsx +15 -9
- package/src/components/data-display/DataViews/data-views-display-tabs.tsx +19 -29
- package/src/components/data-display/DataViews/data-views-export.tsx +9 -10
- package/src/components/data-display/DataViews/data-views-filter-panel.tsx +9 -5
- package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +5 -2
- package/src/components/data-display/DataViews/data-views-more-fields.tsx +5 -3
- package/src/components/data-display/DataViews/data-views-more-filters.tsx +6 -3
- package/src/components/data-display/DataViews/data-views-range-pill.tsx +9 -5
- package/src/components/data-display/DataViews/data-views-range-presets.ts +7 -8
- package/src/components/data-display/DataViews/data-views-scopes.tsx +3 -1
- package/src/components/data-display/DataViews/data-views-search.tsx +7 -4
- package/src/components/data-display/DataViews/data-views-select-all-strip.tsx +5 -3
- package/src/components/data-display/DataViews/data-views-table-parts.tsx +7 -2
- package/src/components/data-display/DataViews/data-views-view-nav.tsx +22 -16
- package/src/components/data-display/DataViews/index.ts +20 -0
- package/src/components/data-display/DataViews/save-view-preview.tsx +78 -0
- package/src/components/data-display/DataViews/use-saved-views-controller.ts +3 -1
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +3 -3
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.types.ts +8 -7
- package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +2 -2
- package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +20 -6
- package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +9 -1
- package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +12 -4
- package/src/components/feedback/ConfirmAction/index.ts +2 -2
- package/src/components/feedback/ConfirmAction/with-confirmation.tsx +4 -3
- package/src/components/form/CategorySelect/CategoryPanel.tsx +18 -6
- package/src/components/form/CategorySelect/CategoryPanelFoot.tsx +10 -5
- package/src/components/form/CategorySelect/CategoryPanelHead.tsx +8 -3
- package/src/components/form/CategorySelect/CategoryPanelList.tsx +17 -10
- package/src/components/form/CategorySelect/CategorySelect.tsx +3 -3
- package/src/components/form/CategorySelect/CategorySelect.types.ts +5 -0
- package/src/components/form/CategorySelect/CategoryTrigger.tsx +5 -1
- package/src/components/form/CepField/CepField.tsx +6 -9
- package/src/components/form/CepField/CepField.types.ts +3 -0
- package/src/components/form/total-form/Fields/CategoryField.tsx +5 -0
- package/src/components/form/total-form/Fields/CepField.tsx +5 -0
- package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +6 -1
- package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +1 -21
- package/src/components/layout/TableFilter/TableFilter.tsx +1 -1
- package/src/copy.ts +103 -0
- package/src/pt-BR.ts +247 -0
- package/dist/chunk-62XQWGXU.js.map +0 -1
- package/dist/chunk-7XLEWBKL.js.map +0 -1
- package/dist/chunk-R4TYXKDD.js.map +0 -1
|
@@ -7,12 +7,11 @@ import {
|
|
|
7
7
|
|
|
8
8
|
// src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts
|
|
9
9
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
|
-
var DEFAULT_ERROR_TEXT = "N\xE3o foi poss\xEDvel concluir a a\xE7\xE3o. Tente novamente.";
|
|
11
10
|
function failureMessage(cause, errorText) {
|
|
12
11
|
if (cause instanceof Error && cause.message) return cause.message;
|
|
13
12
|
return errorText;
|
|
14
13
|
}
|
|
15
|
-
function useConfirmAction(onConfirm, errorText
|
|
14
|
+
function useConfirmAction(onConfirm, errorText) {
|
|
16
15
|
const [open, setOpen] = useState(false);
|
|
17
16
|
const [pending, setPending] = useState(false);
|
|
18
17
|
const [error, setError] = useState(null);
|
|
@@ -59,10 +58,9 @@ function useConfirmAction(onConfirm, errorText = DEFAULT_ERROR_TEXT) {
|
|
|
59
58
|
import { Alert, Stack, TextField, Typography } from "@mui/material";
|
|
60
59
|
import React from "react";
|
|
61
60
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
62
|
-
var DEFAULT_CANCEL_TEXT = "Cancelar";
|
|
63
61
|
var DEFAULT_TEST_ID = "confirm-action";
|
|
64
|
-
function confirmBody(description, entityName) {
|
|
65
|
-
if (!entityName) return description ??
|
|
62
|
+
function confirmBody(description, copy, entityName) {
|
|
63
|
+
if (!entityName) return description ?? copy.irreversible;
|
|
66
64
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
65
|
/* @__PURE__ */ jsx(Typography, { component: "span", sx: { fontWeight: 600, display: "block" }, children: entityName }),
|
|
68
66
|
description
|
|
@@ -103,12 +101,13 @@ function ConfirmActionDialog({
|
|
|
103
101
|
description,
|
|
104
102
|
entityName,
|
|
105
103
|
confirmText,
|
|
106
|
-
cancelText
|
|
104
|
+
cancelText,
|
|
107
105
|
typeToConfirm,
|
|
108
106
|
typeToConfirmLabel,
|
|
109
107
|
tone = "destructive",
|
|
110
108
|
initialFocus,
|
|
111
|
-
dataTestId = DEFAULT_TEST_ID
|
|
109
|
+
dataTestId = DEFAULT_TEST_ID,
|
|
110
|
+
copy
|
|
112
111
|
}) {
|
|
113
112
|
const [typed, setTyped] = React.useState("");
|
|
114
113
|
React.useEffect(() => {
|
|
@@ -121,9 +120,9 @@ function ConfirmActionDialog({
|
|
|
121
120
|
open: state.open,
|
|
122
121
|
variant: tone === "destructive" ? "destructive" : "default",
|
|
123
122
|
title,
|
|
124
|
-
description: confirmBody(description, entityName),
|
|
123
|
+
description: confirmBody(description, copy, entityName),
|
|
125
124
|
confirmText,
|
|
126
|
-
cancelText,
|
|
125
|
+
cancelText: cancelText ?? copy.cancel,
|
|
127
126
|
loading: state.pending,
|
|
128
127
|
confirmDisabled: gateUnmet,
|
|
129
128
|
initialFocus: resolveInitialFocus(tone, initialFocus),
|
|
@@ -183,13 +182,13 @@ function withConfirmation(Wrapped, defaults) {
|
|
|
183
182
|
function WithConfirmation(props) {
|
|
184
183
|
const { confirm, onClick } = props;
|
|
185
184
|
const options = resolveOptions(defaults, confirm);
|
|
186
|
-
const state = useConfirmAction(useGuardedHandler(onClick),
|
|
185
|
+
const state = useConfirmAction(useGuardedHandler(onClick), defaults.errorText);
|
|
187
186
|
const { confirm: _confirm, ...rest } = props;
|
|
188
187
|
const forwarded = rest;
|
|
189
188
|
if (!options) return /* @__PURE__ */ jsx3(Wrapped, { ...forwarded });
|
|
190
189
|
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
191
190
|
/* @__PURE__ */ jsx3(Wrapped, { ...forwarded, onClick: state.request }),
|
|
192
|
-
/* @__PURE__ */ jsx3(ConfirmActionDialog, { state, ...options })
|
|
191
|
+
/* @__PURE__ */ jsx3(ConfirmActionDialog, { state, ...options, copy: defaults.copy })
|
|
193
192
|
] });
|
|
194
193
|
}
|
|
195
194
|
WithConfirmation.displayName = `withConfirmation(${Wrapped.displayName ?? Wrapped.name ?? "Component"})`;
|
|
@@ -197,17 +196,20 @@ function withConfirmation(Wrapped, defaults) {
|
|
|
197
196
|
}
|
|
198
197
|
|
|
199
198
|
// src/components/feedback/ConfirmAction/ConfirmButton.tsx
|
|
200
|
-
|
|
201
|
-
Button,
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
function createConfirmButton(copy, errorText) {
|
|
200
|
+
return withConfirmation(Button, {
|
|
201
|
+
cancelText: copy.cancel,
|
|
202
|
+
tone: "destructive",
|
|
203
|
+
errorText,
|
|
204
|
+
copy
|
|
205
|
+
});
|
|
206
|
+
}
|
|
204
207
|
|
|
205
208
|
export {
|
|
206
|
-
DEFAULT_ERROR_TEXT,
|
|
207
209
|
useConfirmAction,
|
|
208
210
|
ConfirmActionDialog,
|
|
209
211
|
ConfirmAction,
|
|
210
212
|
withConfirmation,
|
|
211
|
-
|
|
213
|
+
createConfirmButton
|
|
212
214
|
};
|
|
213
|
-
//# sourceMappingURL=chunk-
|
|
215
|
+
//# sourceMappingURL=chunk-WFPXRSIZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts","../src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx","../src/components/feedback/ConfirmAction/ConfirmAction.tsx","../src/components/feedback/ConfirmAction/with-confirmation.tsx","../src/components/feedback/ConfirmAction/ConfirmButton.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { ConfirmHandler, UseConfirmActionResult } from './ConfirmAction.types';\n\n/** Used when the guarded action rejects and the caller supplied no wording. */\n\n\n/**\n * What the popup says after a failed attempt.\n *\n * A rejection carrying a message wins: the server's sentence (\"esta categoria\n * ainda tem produtos vinculados\") is the one the operator can act on, and it is\n * strictly better than the generic fallback. Handlers that have nothing useful\n * to say reject with nothing and get `errorText`.\n */\nfunction failureMessage(cause: unknown, errorText: string): string {\n if (cause instanceof Error && cause.message) return cause.message;\n return errorText;\n}\n\n/**\n * The confirmation state machine, headless.\n *\n * It is the whole safety contract in one place, so every consumer gets the same\n * behaviour: the action runs ONLY from `confirm`, never from opening the popup;\n * a second confirm while the first is in flight is dropped (a double-click\n * cannot send two deletes); a rejection keeps the popup open carrying the\n * failure instead of closing over a write that never happened.\n */\nexport function useConfirmAction(\n onConfirm: ConfirmHandler,\n errorText: string,\n): UseConfirmActionResult {\n const [open, setOpen] = useState(false);\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // `pending` is mirrored in a ref because the two guards that matter — drop a\n // second confirm, ignore a cancel mid-flight — are read inside callbacks that\n // must not be rebuilt on every state change. Reading the state variable there\n // would leave a stale closure holding `false` for the whole in-flight window,\n // which is exactly the double-submit this component exists to prevent.\n const busy = useRef(false);\n\n // The action can settle after the trigger has unmounted (a row deleted from\n // under its own menu), so the settle path must not touch state by then.\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n const request = useCallback((): void => {\n setError(null);\n setOpen(true);\n }, []);\n\n const cancel = useCallback((): void => {\n // Inert mid-flight: the write has already left, and closing here would hide\n // its outcome.\n if (busy.current) return;\n setOpen(false);\n setError(null);\n }, []);\n\n const settle = useCallback((failure: string | null): void => {\n busy.current = false;\n if (!mounted.current) return;\n setPending(false);\n setError(failure);\n if (!failure) setOpen(false);\n }, []);\n\n const confirm = useCallback((): void => {\n if (busy.current) return;\n busy.current = true;\n setPending(true);\n setError(null);\n // The handler is invoked synchronously, exactly as a plain `onClick` would\n // be — only the OUTCOME is awaited. The try/catch is what puts a handler\n // that throws synchronously on the same failure path as one that returns a\n // rejected promise.\n try {\n const result = onConfirm();\n void Promise.resolve(result)\n .then(() => settle(null))\n .catch((cause: unknown) => settle(failureMessage(cause, errorText)));\n } catch (cause) {\n settle(failureMessage(cause, errorText));\n }\n }, [errorText, onConfirm, settle]);\n\n return { open, pending, error, request, cancel, confirm };\n}\n","import type { ConfirmActionCopy } from \"../../../copy\";\nimport { Alert, Stack, TextField, Typography } from '@mui/material';\nimport React, { type ReactNode } from 'react';\n\nimport { AlertDialog } from '../../data-display/AlertDialog';\n\nimport type {\n ConfirmInitialFocus,\n ConfirmOptions,\n ConfirmTone,\n UseConfirmActionResult,\n} from './ConfirmAction.types';\n\nconst DEFAULT_TEST_ID = 'confirm-action';\n\n/**\n * The popup's body: the row being acted on, then what happens to it.\n *\n * The NAME is rendered in its own right rather than woven into the sentence, so\n * it is there whatever the caller wrote — \"the popup names the specific entity\"\n * is the one thing that must not depend on each call site remembering to\n * mention it. A body with neither a name nor a description would leave the\n * operator with only the title to decide on, so a neutral fallback covers that.\n */\nfunction confirmBody(\n description: ReactNode,\n copy: ConfirmActionCopy,\n entityName?: string,\n): ReactNode {\n if (!entityName) return description ?? copy.irreversible;\n return (\n <>\n <Typography component=\"span\" sx={{ fontWeight: 600, display: \"block\" }}>\n {entityName}\n </Typography>\n {description}\n </>\n );\n}\n\n/** Destructive dialogs open on Cancel; anything else opens on the confirm. */\nfunction resolveInitialFocus(\n tone: ConfirmTone,\n initialFocus?: ConfirmInitialFocus,\n): ConfirmInitialFocus {\n if (initialFocus) return initialFocus;\n return tone === 'destructive' ? 'cancel' : 'confirm';\n}\n\n/**\n * The type-to-confirm field. Rendered only when `typeToConfirm` is set, which\n * should be rare: it is the guard for actions with NO recovery path, where a\n * click is too cheap a gesture. Comparison is exact — trimmed of surrounding\n * whitespace only, so a trailing space from a paste does not read as a mismatch.\n */\nfunction TypeToConfirmField({\n expected,\n label,\n value,\n onChange,\n disabled,\n dataTestId,\n}: {\n expected: string;\n label?: string;\n value: string;\n onChange: (next: string) => void;\n disabled: boolean;\n dataTestId: string;\n}): React.ReactElement {\n return (\n <Stack spacing={1} sx={{ mt: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label ?? `Digite \"${expected}\" para confirmar.`}\n </Typography>\n <TextField\n size=\"small\"\n value={value}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value)}\n // On the INPUT rather than the wrapper: a test id on MUI's TextField\n // lands on the outer div, which is not the node a test can type into.\n inputProps={{\n 'aria-label': label ?? `Digite ${expected} para confirmar`,\n 'data-testid': `${dataTestId}-type-to-confirm`,\n }}\n />\n </Stack>\n );\n}\n\nexport interface ConfirmActionDialogProps extends ConfirmOptions {\n /** The fallback body when no entity is named. REQUIRED — no default copy. */\n copy: ConfirmActionCopy;\n state: UseConfirmActionResult;\n}\n\n/**\n * The popup itself: an `AlertDialog` in its destructive skin, plus the two\n * things a bare AlertDialog has no opinion about — the failure the last attempt\n * produced (shown IN the dialog, which stays open, rather than closing over a\n * write that never landed) and the optional type-to-confirm gate.\n */\nexport function ConfirmActionDialog({\n state,\n title,\n description,\n entityName,\n confirmText,\n cancelText,\n typeToConfirm,\n typeToConfirmLabel,\n tone = 'destructive',\n initialFocus,\n dataTestId = DEFAULT_TEST_ID,\n copy,\n}: ConfirmActionDialogProps): React.ReactElement {\n const [typed, setTyped] = React.useState('');\n\n // Every fresh open starts from an empty field: carrying the previous answer\n // over would hand the next delete a pre-satisfied gate.\n React.useEffect(() => {\n if (state.open) setTyped('');\n }, [state.open]);\n\n const gateUnmet = typeToConfirm !== undefined && typed.trim() !== typeToConfirm;\n\n return (\n <AlertDialog\n open={state.open}\n variant={tone === 'destructive' ? 'destructive' : 'default'}\n title={title}\n description={confirmBody(description, copy, entityName)}\n confirmText={confirmText}\n // `copy.cancel` is the fallback, NOT `AlertDialog`'s own. The 6.3.0 copy\n // sweep deleted this component's `cancelText = 'Cancelar'` default and\n // put the word in `ConfirmActionCopy` — where nothing then read it, so\n // every confirmation that names no `cancelText` of its own fell through\n // to `AlertDialog`'s English `'Cancel'`, in a pt-BR dialog. That is the\n // precise failure the sweep exists to prevent, one layer down: a port\n // that is required, supplied, and ignored.\n cancelText={cancelText ?? copy.cancel}\n loading={state.pending}\n confirmDisabled={gateUnmet}\n initialFocus={resolveInitialFocus(tone, initialFocus)}\n onConfirm={state.confirm}\n onCancel={state.cancel}\n onClose={state.cancel}\n data-testid={dataTestId}\n >\n {state.error && (\n <Alert severity=\"error\" sx={{ mt: 1 }} data-testid={`${dataTestId}-error`}>\n {state.error}\n </Alert>\n )}\n {typeToConfirm !== undefined && (\n <TypeToConfirmField\n expected={typeToConfirm}\n label={typeToConfirmLabel}\n value={typed}\n onChange={setTyped}\n disabled={state.pending}\n dataTestId={dataTestId}\n />\n )}\n </AlertDialog>\n );\n}\n","import React from 'react';\n\nimport { useConfirmAction } from './ConfirmAction.hooks';\nimport { ConfirmActionDialog } from './ConfirmAction.parts';\nimport type { ConfirmActionProps } from './ConfirmAction.types';\n\n/**\n * Wraps any trigger in a confirmation popup.\n *\n * The trigger is a render prop rather than a fixed element, so the same guard\n * covers a button, a dropdown item, an icon or a table row action without this\n * component knowing what any of them look like. The guarded handler runs ONLY\n * after the operator confirms:\n *\n * ```tsx\n * <ConfirmAction\n * title=\"Excluir a categoria?\"\n * entityName={row.name}\n * description=\"Ela vai para a lixeira e pode ser restaurada de lá.\"\n * confirmText=\"Excluir\"\n * onConfirm={() => deleteCategoryAction({ tenantSlug, id: row.id })}\n * >\n * {(request) => <Button color=\"danger\" onClick={request}>Excluir</Button>}\n * </ConfirmAction>\n * ```\n *\n * For the common case — an existing button whose `onClick` is already the\n * destructive write — reach for {@link withConfirmation} instead, which needs\n * no restructuring of the call site.\n */\nexport function ConfirmAction({\n onConfirm,\n children,\n ...options\n}: ConfirmActionProps): React.ReactElement {\n const state = useConfirmAction(onConfirm, options.errorText);\n\n return (\n <>\n {children(state.request, { pending: state.pending })}\n <ConfirmActionDialog state={state} {...options} />\n </>\n );\n}\n\nConfirmAction.displayName = 'ConfirmAction';\n","import type { ConfirmActionCopy } from '../../../copy';\nimport React from 'react';\nimport type { ComponentType } from 'react';\n\nimport { useConfirmAction } from './ConfirmAction.hooks';\nimport { ConfirmActionDialog } from './ConfirmAction.parts';\nimport type {\n ConfirmHandler,\n ConfirmOptions,\n ConfirmableComponent,\n ConfirmableProps,\n WithConfirmationProps,\n} from './ConfirmAction.types';\n\n/**\n * Merge the HOC's baked-in defaults with the per-instance `confirm` prop.\n * Returns null when the instance opts out (`confirm={false}`) or when neither\n * side supplies the two fields a confirmation cannot be written without — the\n * question and the verb. A null result means \"render the plain component\",\n * which keeps the wrapped export usable in harmless contexts.\n */\nfunction resolveOptions(\n defaults: Partial<ConfirmOptions> | undefined,\n instance: Partial<ConfirmOptions> | false | undefined,\n): ConfirmOptions | null {\n if (instance === false) return null;\n const merged = { ...defaults, ...instance };\n if (!merged.title || !merged.confirmText) return null;\n return { ...merged, title: merged.title, confirmText: merged.confirmText };\n}\n\n/**\n * Adapt the wrapped component's `onClick` into a {@link ConfirmHandler}.\n *\n * The click argument is dropped (see `ConfirmHandler`) and the return value is\n * narrowed: a promise is handed back so the popup can hold its pending state\n * until the write settles, anything else becomes `undefined`. A component with\n * no `onClick` has nothing to guard, so confirming is a no-op.\n */\nfunction useGuardedHandler(onClick: ConfirmableProps['onClick']): ConfirmHandler {\n return React.useCallback((): void | Promise<unknown> => {\n const result = onClick?.();\n return result instanceof Promise ? result : undefined;\n }, [onClick]);\n}\n\n/**\n * Give any click-driven component a confirmation popup, without restructuring\n * the call site.\n *\n * The wrapped component's own `onClick` becomes the GUARDED action: clicking\n * now opens the popup, and the handler runs only if the operator confirms. It\n * inherits the whole contract from `useConfirmAction` — cancel sends nothing, a\n * returned promise holds the popup in its pending state so a double-click\n * cannot fire two writes, and a rejection keeps the popup open carrying the\n * error.\n *\n * ```tsx\n * const ConfirmButton = withConfirmation(Button);\n *\n * <ConfirmButton\n * color=\"danger\"\n * onClick={() => deleteCategoryAction({ tenantSlug, id: row.id })}\n * confirm={{\n * title: \"Excluir a categoria?\",\n * entityName: row.name,\n * description: \"Ela vai para a lixeira e pode ser restaurada de lá.\",\n * confirmText: \"Excluir\",\n * }}\n * >\n * Excluir\n * </ConfirmButton>\n * ```\n *\n * Bake the wording in once when the same guard repeats — `withConfirmation(Button,\n * { confirmText: \"Excluir\" })` — and let each instance override what differs.\n * `confirm={false}` falls through to the plain component.\n *\n * Refs are not forwarded: the HOC renders a fragment (trigger + popup), so there\n * is no single node to hand back. Wrap a component that needs a ref at its own\n * call site with {@link ConfirmAction} instead.\n */\nexport function withConfirmation<P extends ConfirmableProps>(\n Wrapped: ComponentType<P>,\n defaults: Partial<ConfirmOptions> & { errorText: string; copy: ConfirmActionCopy },\n): ConfirmableComponent<P> {\n function WithConfirmation(props: P & WithConfirmationProps): React.ReactElement {\n const { confirm, onClick } = props;\n const options = resolveOptions(defaults, confirm);\n const state = useConfirmAction(useGuardedHandler(onClick), defaults.errorText);\n\n // `confirm` is ours and must not reach the DOM — an unknown attribute on a\n // <button> is a React warning at every render. The cast is the standard HOC\n // one: TypeScript cannot prove `Omit<P & X, 'confirm'>` is still a `P`.\n const { confirm: _confirm, ...rest } = props;\n const forwarded = rest as unknown as P;\n\n if (!options) return <Wrapped {...forwarded} />;\n\n return (\n <>\n <Wrapped {...forwarded} onClick={state.request} />\n <ConfirmActionDialog state={state} {...options} copy={defaults.copy} />\n </>\n );\n }\n\n WithConfirmation.displayName = `withConfirmation(${\n Wrapped.displayName ?? Wrapped.name ?? 'Component'\n })`;\n\n return WithConfirmation;\n}\n","import type { ConfirmActionCopy } from '../../../copy';\nimport { Button } from '../../form/Button';\nimport type { ButtonProps } from '../../form/Button/Button.types';\n\nimport { withConfirmation } from './with-confirmation';\nimport type { ConfirmableComponent } from './ConfirmAction.types';\n\n/**\n * The library `Button`, already wrapped — the shape most call sites want.\n *\n * Adding the guard to an existing button is then an import swap plus the\n * `confirm` prop; the button's own props (colour, size, icon) are untouched.\n * The baked-in defaults are only the wording and tone every destructive\n * confirmation shares, and each instance can still override them.\n */\nexport function createConfirmButton(\n copy: ConfirmActionCopy,\n errorText: string,\n): ConfirmableComponent<ButtonProps> {\n return withConfirmation<ButtonProps>(Button, {\n cancelText: copy.cancel,\n tone: 'destructive',\n errorText,\n copy,\n });\n}\n"],"mappings":"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","names":["Fragment","jsx","jsxs","React","Fragment","jsx","jsxs","React"]}
|
package/dist/copy.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=copy.js.map
|
package/dist/copy.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
ConfirmActionDialog,
|
|
6
6
|
useConfirmAction
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-WFPXRSIZ.js";
|
|
8
8
|
import {
|
|
9
9
|
Alert
|
|
10
10
|
} from "../chunk-3KWD5Y5O.js";
|
|
@@ -195,7 +195,8 @@ function useRowConfirm({
|
|
|
195
195
|
write,
|
|
196
196
|
describe,
|
|
197
197
|
dataTestId,
|
|
198
|
-
errorText
|
|
198
|
+
errorText,
|
|
199
|
+
copy
|
|
199
200
|
}) {
|
|
200
201
|
const [target, setTarget] = useState2(null);
|
|
201
202
|
const state = useConfirmAction(async () => {
|
|
@@ -210,7 +211,15 @@ function useRowConfirm({
|
|
|
210
211
|
};
|
|
211
212
|
return {
|
|
212
213
|
request,
|
|
213
|
-
dialog: target ? /* @__PURE__ */ jsx4(
|
|
214
|
+
dialog: target ? /* @__PURE__ */ jsx4(
|
|
215
|
+
ConfirmActionDialog,
|
|
216
|
+
{
|
|
217
|
+
state,
|
|
218
|
+
copy,
|
|
219
|
+
...describe(target),
|
|
220
|
+
dataTestId
|
|
221
|
+
}
|
|
222
|
+
) : null
|
|
214
223
|
};
|
|
215
224
|
}
|
|
216
225
|
|
|
@@ -223,7 +232,8 @@ function useRemoveConfirm({
|
|
|
223
232
|
description,
|
|
224
233
|
confirmText,
|
|
225
234
|
fallbackError,
|
|
226
|
-
dataTestId
|
|
235
|
+
dataTestId,
|
|
236
|
+
copy
|
|
227
237
|
}) {
|
|
228
238
|
const { onRefresh, notifyError } = useCardActions();
|
|
229
239
|
const state = useConfirmAction(async () => {
|
|
@@ -241,6 +251,7 @@ function useRemoveConfirm({
|
|
|
241
251
|
ConfirmActionDialog,
|
|
242
252
|
{
|
|
243
253
|
state,
|
|
254
|
+
copy,
|
|
244
255
|
title,
|
|
245
256
|
entityName,
|
|
246
257
|
description,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/data-display/CardKit/CardKebab.tsx","../../src/components/data-display/CardKit/card-actions-context.tsx","../../src/components/data-display/CardKit/row-actions-to-menu.ts","../../src/components/data-display/CardKit/list-card-parts.tsx","../../src/components/data-display/CardKit/use-row-confirm.tsx","../../src/components/data-display/CardKit/use-remove-confirm.tsx"],"sourcesContent":["'use client';\n\nimport type { JSX } from 'react';\n\nimport { Button } from '../../form/Button';\nimport { DropdownMenu, type DropdownMenuItem } from '../../navigation/DropdownMenu';\n\n/**\n * The \"⋮\" trigger every row and card menu opens from.\n *\n * One component rather than a `DropdownMenu` per entity, so the kebab looks and\n * behaves identically in the card, in the list row and in the table row. The\n * entity's menu owns its own popups; this is the trigger and the item list.\n */\nexport function CardKebab({\n items,\n menuLabel,\n dataTestId,\n}: {\n items: DropdownMenuItem[];\n /**\n * The trigger's accessible name — required, and with no default.\n *\n * It is the only text this component renders, and a screen reader announces\n * it verbatim. A default here would be a word in the origin's language that\n * reads as finished to the next adopter right up until somebody using a\n * screen reader meets it.\n */\n menuLabel: string;\n dataTestId?: string;\n}): JSX.Element {\n return (\n <DropdownMenu\n size=\"sm\"\n items={items}\n trigger={\n <Button variant=\"text\" size=\"sm\" aria-label={menuLabel} dataTestId={dataTestId}>\n ⋮\n </Button>\n }\n />\n );\n}\n","'use client';\n\nimport { createContext, useCallback, useContext, useState, type JSX, type ReactNode } from 'react';\n\nimport { Snackbar } from '@mui/material';\n\nimport { Alert } from '../Alert';\n\n/**\n * The ambient wiring a self-contained row/card menu needs, and nothing else.\n *\n * A menu that owns its own popups still needs three things it cannot know: the\n * tenant it is acting inside, what to do after a write lands, and somewhere to\n * put a failure. Passing those down through the grid, the layout and the card\n * is four props of drilling per entity; holding them in context is one.\n *\n * Kept deliberately SMALL — it is not an edit-dialog host. A menu that read its\n * dialogs from here would stop being portable, because the set of dialogs is\n * per-entity. What it may read is the three facts below.\n *\n * The provider renders ONE shared error snackbar, which is the whole reason the\n * error channel is here rather than per-menu: before it, every page carried its\n * own error alert and every menu had to find its page's.\n */\ninterface CardActionsValue {\n /** The tenant every action in this subtree acts inside. */\n tenantSlug: string;\n /** Re-read the list after a write. */\n onRefresh: () => void;\n /** Surface a failed action's message (the shared snackbar). */\n notifyError: (message: string) => void;\n}\n\nconst CardActionsContext = createContext<CardActionsValue | null>(null);\n\nexport function CardActionsProvider({\n tenantSlug,\n onRefresh,\n errorTitle,\n autoHideMs = 6_000,\n children,\n}: {\n tenantSlug: string;\n onRefresh: () => void;\n /**\n * The snackbar's heading — required, no default.\n *\n * It is the one sentence this provider renders on its own, and a default\n * would be the origin's language shipped as a finished-looking silence. The\n * MESSAGE beside it comes from whatever failed, which is already the host's.\n */\n errorTitle: string;\n /** How long the snackbar stays up. */\n autoHideMs?: number;\n children: ReactNode;\n}): JSX.Element {\n const [error, setError] = useState<string | null>(null);\n const notifyError = useCallback((message: string) => setError(message), []);\n\n return (\n <CardActionsContext.Provider value={{ tenantSlug, onRefresh, notifyError }}>\n {children}\n <Snackbar\n open={error !== null}\n autoHideDuration={autoHideMs}\n onClose={() => setError(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}\n >\n <span>\n <Alert\n variant=\"danger\"\n title={errorTitle}\n description={error ?? ''}\n closable\n onClose={() => setError(null)}\n data-testid=\"card-action-error\"\n />\n </span>\n </Snackbar>\n </CardActionsContext.Provider>\n );\n}\n\n/**\n * Read the tenant + refresh + error wiring.\n *\n * THROWS outside a provider rather than answering a null object, deliberately:\n * a menu whose `onRefresh` silently did nothing would leave the operator\n * looking at a stale row after a delete that worked, which reads as the delete\n * having failed. Failing at mount says where the provider is missing.\n */\nexport function useCardActions(): CardActionsValue {\n const value = useContext(CardActionsContext);\n if (!value) {\n throw new Error('useCardActions must be used within a CardActionsProvider');\n }\n return value;\n}\n","import type { DropdownMenuItem } from '../../navigation/DropdownMenu';\nimport type { RowAction } from '../DataViews';\n\n/**\n * Adapt a list of {@link RowAction}s into single-row kebab items.\n *\n * Applies each action's `isVisible` guard, resolves its per-row `rowLabel`\n * override, carries its colour, and fires `onSelect([row])` on click.\n *\n * The point is that ONE definition drives both surfaces. An entity that already\n * declares its per-row actions as `RowAction[]` — because the table's multi-\n * select menu needs them — gets the card's kebab from the same array through\n * `renderRowMenu` / `renderCard`, with no second list to keep in step. Two\n * lists is how a \"Duplicar\" that appears in the table and not on the card\n * happens, and nothing reports it.\n */\nexport function rowActionsToMenuItems<T extends Record<string, unknown>>(\n actions: RowAction<T>[],\n row: T,\n): DropdownMenuItem[] {\n return actions\n .filter((action) => action.isVisible?.(row) ?? true)\n .map((action) => ({\n id: action.id,\n label: action.rowLabel?.(row) ?? action.label,\n color: action.color,\n onClick: () => void action.onSelect([row]),\n }));\n}\n","'use client';\n\nimport type { JSX, ReactNode } from 'react';\n\nimport { Box } from '../../../mui/Box';\n\nimport type { CardFactProps, CardLedgerLine } from './CardKit.types';\n\n/**\n * THE SHARED FURNITURE OF AN EXPANDED LIST-CARD BODY.\n *\n * `BaseListCard` says nothing about what goes inside a row's expanded area — it\n * spans the rails and stops, because the design belongs to the consumer. Right\n * for the card; wrong as the place where every entity in an admin app invents\n * its own two-column layout, its own label/value pair and its own ledger.\n *\n * So the four shapes that actually repeat live here, once. Nothing here knows a\n * domain: they take `ReactNode` and lay it out.\n */\n\n/** The expanded body's two-column split: detail on the left, a ledger right. */\nexport function DetailColumns({ left, right }: { left: ReactNode; right: ReactNode }): JSX.Element {\n return (\n <Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', md: '1fr 1fr' }, gap: 3 }}>\n <Box sx={{ minWidth: 0 }}>{left}</Box>\n <Box sx={{ minWidth: 0 }}>{right}</Box>\n </Box>\n );\n}\n\n/**\n * One labelled fact inside an expanded body.\n *\n * Horizontal, not stacked: the body is already a wide area with room for a\n * label beside its value, and stacking them there would ape the summary rails\n * above without their alignment.\n */\nexport function Fact({ label, value }: CardFactProps): JSX.Element {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'space-between', gap: 2, fontSize: 13, py: 0.25 }}>\n <Box component=\"span\" sx={{ color: 'text.secondary', flexShrink: 0 }}>\n {label}\n </Box>\n <Box component=\"span\" sx={{ minWidth: 0, textAlign: 'right', overflowWrap: 'anywhere' }}>\n {value}\n </Box>\n </Box>\n );\n}\n\n/**\n * A money ledger: rows of label/amount, then a ruled total.\n *\n * The total is separated by a RULE rather than by weight alone, because a\n * subtotal and a total in one column with only bold between them is the classic\n * misread — the eye lands on whichever number is larger.\n *\n * The figures arrive pre-formatted. This is a layout, and a component that\n * formatted money would be choosing a locale on the consumer's behalf.\n */\nexport function Ledger({\n lines,\n total,\n}: {\n lines: CardLedgerLine[];\n total: { label: string; value: ReactNode };\n}): JSX.Element {\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.25 }}>\n {lines.map((line) => (\n <Box\n key={line.label}\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n fontSize: 13,\n color: line.tone === 'info' ? 'info.main' : 'text.secondary',\n }}\n >\n <Box component=\"span\">{line.label}</Box>\n <Box component=\"span\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {line.value}\n </Box>\n </Box>\n ))}\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n fontWeight: 700,\n borderTop: 1,\n borderColor: 'divider',\n pt: 0.5,\n mt: 0.5,\n }}\n >\n <Box component=\"span\">{total.label}</Box>\n <Box component=\"span\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {total.value}\n </Box>\n </Box>\n </Box>\n );\n}\n\n/** A heading inside the expanded body, for a section that needs naming. */\nexport function BodyHeading({ children }: { children: ReactNode }): JSX.Element {\n return (\n <Box\n sx={{\n fontSize: 11,\n fontWeight: 700,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n color: 'text.disabled',\n mb: 0.5,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * A wrapping run of small items — permission names, role names, target ids.\n *\n * The whole reason several entities earn a list card at all: a `string[]` has no\n * honest table cell. Truncated to \"3 items\" it says nothing; printed in full it\n * destroys the column. Here it simply wraps.\n */\nexport function TagList({\n items,\n empty,\n}: {\n items: readonly string[];\n /** What to show for an empty run — the consumer's sentence, no default. */\n empty: string;\n}): JSX.Element {\n if (items.length === 0) {\n return <Box sx={{ fontSize: 13, color: 'text.disabled' }}>{empty}</Box>;\n }\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {items.map((item) => (\n <Box\n key={item}\n component=\"span\"\n sx={{\n fontSize: 12,\n px: 0.75,\n py: 0.25,\n borderRadius: 1,\n bgcolor: 'action.hover',\n color: 'text.secondary',\n fontFamily: 'monospace',\n }}\n >\n {item}\n </Box>\n ))}\n </Box>\n );\n}\n","'use client';\n\nimport { useState, type JSX } from 'react';\n\nimport { ConfirmActionDialog, useConfirmAction } from '../../feedback/ConfirmAction';\n\n/**\n * How the popup should read for the rows about to be acted on.\n *\n * Built from the SELECTION rather than from a single row, because the same\n * guard covers a bulk action: \"Delete 4 categories?\" and \"Delete the category\n * Drinks?\" are the same question asked of a different-sized selection — and an\n * operator who multi-selected by mistake is exactly who this popup is for.\n */\nexport interface RowConfirmCopy {\n title: string;\n description: string;\n /** Echoed into the popup; omit for a multi-row selection the title covers. */\n entityName?: string;\n /** The VERB. Required, never defaulted — see {@link useRowConfirm}. */\n confirmText: string;\n /** Override where the word \"cancel\" would mean the ACTION itself. */\n cancelText?: string;\n /** Require typing this before the confirm enables — for the unrecoverable few. */\n typeToConfirm?: string;\n}\n\ninterface RowConfirmOptions<T> {\n /**\n * The destructive write, over the whole selection. Called ONLY after the\n * operator confirms; throw (or reject) to keep the popup open carrying the\n * message.\n */\n write: (rows: T[]) => Promise<unknown>;\n /** The wording, given the selection. */\n describe: (rows: T[]) => RowConfirmCopy;\n dataTestId: string;\n /** Shown when `write` fails without a message of its own. */\n errorText?: string;\n}\n\nexport interface RowConfirm<T> {\n /** Hand this a grid action's `rows`: it opens the popup and writes nothing. */\n request: (rows: T[]) => void;\n /** Render next to the grid. */\n dialog: JSX.Element | null;\n}\n\n/**\n * Confirmation for a grid's `RowAction` — the per-row kebab entry and the\n * multi-select actions menu both, since they run the same handler.\n *\n * The SELECTION is held while the popup is open, so the write sees exactly the\n * rows the operator was looking at when they were asked. Re-reading the grid's\n * live selection at confirm time is the bug this shape avoids: the list can\n * refresh underneath an open dialog.\n *\n * `confirmText` is required and comes from `describe`, with no default. A verb\n * defaulted in the origin's language reads as finished to the next adopter\n * right up until an operator sees it — and `ConfirmOptions` already refuses to\n * default one for the same reason.\n */\nexport function useRowConfirm<T>({\n write,\n describe,\n dataTestId,\n errorText,\n}: RowConfirmOptions<T>): RowConfirm<T> {\n const [target, setTarget] = useState<T[] | null>(null);\n\n const state = useConfirmAction(async () => {\n if (!target) return;\n await write(target);\n setTarget(null);\n }, errorText);\n\n const request = (rows: T[]): void => {\n // An empty selection has nothing to confirm — asking would be a popup about\n // nothing, and confirming it would write nothing.\n if (rows.length === 0) return;\n setTarget(rows);\n state.request();\n };\n\n return {\n request,\n dialog: target ? (\n <ConfirmActionDialog state={state} {...describe(target)} dataTestId={dataTestId} />\n ) : null,\n };\n}\n","'use client';\n\nimport type { JSX } from 'react';\n\nimport { ConfirmActionDialog, useConfirmAction } from '../../feedback/ConfirmAction';\n\nimport { useCardActions } from './card-actions-context';\n\n/** The `{ ok, error }` envelope a write action answers with. */\nexport interface CardWriteResult {\n ok: boolean;\n error?: string;\n}\n\ninterface RemoveConfirmOptions {\n /** The destructive write. Called ONLY after the operator confirms. */\n write: () => Promise<CardWriteResult>;\n /** The popup's question. */\n title: string;\n /** The row being removed, echoed into the popup so it names a thing. */\n entityName: string;\n /**\n * What happens, and whether it can be walked back. Say which — the difference\n * between a soft delete a recycle bin recovers and one nothing recovers is\n * the whole content of the decision being asked for.\n */\n description: string;\n /** The confirm button's VERB. Required, never defaulted. */\n confirmText: string;\n /** Used when the write fails without a message of its own. */\n fallbackError: string;\n dataTestId: string;\n}\n\ninterface RemoveConfirm {\n /** Hand this to the menu item's `onClick`: it opens the popup, nothing more. */\n request: () => void;\n /** Render alongside the trigger. */\n dialog: JSX.Element;\n}\n\n/**\n * The confirm-before-removing wiring every card/row menu repeats, in one place.\n *\n * It closes the three gaps a hand-rolled version keeps re-opening: the write\n * leaves ONLY on confirm; a refusal is surfaced twice — inside the popup, where\n * the operator is still deciding, and in the shared snackbar behind it — and a\n * failed attempt leaves the popup OPEN to be retried instead of vanishing over\n * a delete that never happened.\n *\n * The difference from {@link useRowConfirm} is which surface it serves: this one\n * is for a SELF-CONTAINED menu that already sits inside a\n * `CardActionsProvider`, so it reads the refresh and the error channel from\n * context and answers the `{ ok, error }` envelope those actions use.\n * `useRowConfirm` is for a grid whose actions are declared as `RowAction[]` and\n * act on a selection.\n *\n * ```tsx\n * const remove = useRemoveConfirm({\n * write: () => deleteCategory({ tenantSlug, id: row.id }),\n * title: copy.deleteTitle,\n * entityName: row.name,\n * description: copy.deleteDescription,\n * confirmText: copy.delete,\n * fallbackError: copy.deleteFailed,\n * dataTestId: 'category-delete-confirm',\n * });\n * ```\n */\nexport function useRemoveConfirm({\n write,\n title,\n entityName,\n description,\n confirmText,\n fallbackError,\n dataTestId,\n}: RemoveConfirmOptions): RemoveConfirm {\n const { onRefresh, notifyError } = useCardActions();\n\n const state = useConfirmAction(async () => {\n const result = await write();\n if (!result.ok) {\n const message = result.error ?? fallbackError;\n notifyError(message);\n // Rejecting is what keeps the popup open carrying `message`; the snackbar\n // above is what remains once the operator dismisses it.\n throw new Error(message);\n }\n onRefresh();\n }, fallbackError);\n\n return {\n request: state.request,\n dialog: (\n <ConfirmActionDialog\n state={state}\n title={title}\n entityName={entityName}\n description={description}\n confirmText={confirmText}\n dataTestId={dataTestId}\n />\n ),\n };\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","useState","jsx","useState","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/data-display/CardKit/CardKebab.tsx","../../src/components/data-display/CardKit/card-actions-context.tsx","../../src/components/data-display/CardKit/row-actions-to-menu.ts","../../src/components/data-display/CardKit/list-card-parts.tsx","../../src/components/data-display/CardKit/use-row-confirm.tsx","../../src/components/data-display/CardKit/use-remove-confirm.tsx"],"sourcesContent":["'use client';\n\nimport type { JSX } from 'react';\n\nimport { Button } from '../../form/Button';\nimport { DropdownMenu, type DropdownMenuItem } from '../../navigation/DropdownMenu';\n\n/**\n * The \"⋮\" trigger every row and card menu opens from.\n *\n * One component rather than a `DropdownMenu` per entity, so the kebab looks and\n * behaves identically in the card, in the list row and in the table row. The\n * entity's menu owns its own popups; this is the trigger and the item list.\n */\nexport function CardKebab({\n items,\n menuLabel,\n dataTestId,\n}: {\n items: DropdownMenuItem[];\n /**\n * The trigger's accessible name — required, and with no default.\n *\n * It is the only text this component renders, and a screen reader announces\n * it verbatim. A default here would be a word in the origin's language that\n * reads as finished to the next adopter right up until somebody using a\n * screen reader meets it.\n */\n menuLabel: string;\n dataTestId?: string;\n}): JSX.Element {\n return (\n <DropdownMenu\n size=\"sm\"\n items={items}\n trigger={\n <Button variant=\"text\" size=\"sm\" aria-label={menuLabel} dataTestId={dataTestId}>\n ⋮\n </Button>\n }\n />\n );\n}\n","'use client';\n\nimport { createContext, useCallback, useContext, useState, type JSX, type ReactNode } from 'react';\n\nimport { Snackbar } from '@mui/material';\n\nimport { Alert } from '../Alert';\n\n/**\n * The ambient wiring a self-contained row/card menu needs, and nothing else.\n *\n * A menu that owns its own popups still needs three things it cannot know: the\n * tenant it is acting inside, what to do after a write lands, and somewhere to\n * put a failure. Passing those down through the grid, the layout and the card\n * is four props of drilling per entity; holding them in context is one.\n *\n * Kept deliberately SMALL — it is not an edit-dialog host. A menu that read its\n * dialogs from here would stop being portable, because the set of dialogs is\n * per-entity. What it may read is the three facts below.\n *\n * The provider renders ONE shared error snackbar, which is the whole reason the\n * error channel is here rather than per-menu: before it, every page carried its\n * own error alert and every menu had to find its page's.\n */\ninterface CardActionsValue {\n /** The tenant every action in this subtree acts inside. */\n tenantSlug: string;\n /** Re-read the list after a write. */\n onRefresh: () => void;\n /** Surface a failed action's message (the shared snackbar). */\n notifyError: (message: string) => void;\n}\n\nconst CardActionsContext = createContext<CardActionsValue | null>(null);\n\nexport function CardActionsProvider({\n tenantSlug,\n onRefresh,\n errorTitle,\n autoHideMs = 6_000,\n children,\n}: {\n tenantSlug: string;\n onRefresh: () => void;\n /**\n * The snackbar's heading — required, no default.\n *\n * It is the one sentence this provider renders on its own, and a default\n * would be the origin's language shipped as a finished-looking silence. The\n * MESSAGE beside it comes from whatever failed, which is already the host's.\n */\n errorTitle: string;\n /** How long the snackbar stays up. */\n autoHideMs?: number;\n children: ReactNode;\n}): JSX.Element {\n const [error, setError] = useState<string | null>(null);\n const notifyError = useCallback((message: string) => setError(message), []);\n\n return (\n <CardActionsContext.Provider value={{ tenantSlug, onRefresh, notifyError }}>\n {children}\n <Snackbar\n open={error !== null}\n autoHideDuration={autoHideMs}\n onClose={() => setError(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}\n >\n <span>\n <Alert\n variant=\"danger\"\n title={errorTitle}\n description={error ?? ''}\n closable\n onClose={() => setError(null)}\n data-testid=\"card-action-error\"\n />\n </span>\n </Snackbar>\n </CardActionsContext.Provider>\n );\n}\n\n/**\n * Read the tenant + refresh + error wiring.\n *\n * THROWS outside a provider rather than answering a null object, deliberately:\n * a menu whose `onRefresh` silently did nothing would leave the operator\n * looking at a stale row after a delete that worked, which reads as the delete\n * having failed. Failing at mount says where the provider is missing.\n */\nexport function useCardActions(): CardActionsValue {\n const value = useContext(CardActionsContext);\n if (!value) {\n throw new Error('useCardActions must be used within a CardActionsProvider');\n }\n return value;\n}\n","import type { DropdownMenuItem } from '../../navigation/DropdownMenu';\nimport type { RowAction } from '../DataViews';\n\n/**\n * Adapt a list of {@link RowAction}s into single-row kebab items.\n *\n * Applies each action's `isVisible` guard, resolves its per-row `rowLabel`\n * override, carries its colour, and fires `onSelect([row])` on click.\n *\n * The point is that ONE definition drives both surfaces. An entity that already\n * declares its per-row actions as `RowAction[]` — because the table's multi-\n * select menu needs them — gets the card's kebab from the same array through\n * `renderRowMenu` / `renderCard`, with no second list to keep in step. Two\n * lists is how a \"Duplicar\" that appears in the table and not on the card\n * happens, and nothing reports it.\n */\nexport function rowActionsToMenuItems<T extends Record<string, unknown>>(\n actions: RowAction<T>[],\n row: T,\n): DropdownMenuItem[] {\n return actions\n .filter((action) => action.isVisible?.(row) ?? true)\n .map((action) => ({\n id: action.id,\n label: action.rowLabel?.(row) ?? action.label,\n color: action.color,\n onClick: () => void action.onSelect([row]),\n }));\n}\n","'use client';\n\nimport type { JSX, ReactNode } from 'react';\n\nimport { Box } from '../../../mui/Box';\n\nimport type { CardFactProps, CardLedgerLine } from './CardKit.types';\n\n/**\n * THE SHARED FURNITURE OF AN EXPANDED LIST-CARD BODY.\n *\n * `BaseListCard` says nothing about what goes inside a row's expanded area — it\n * spans the rails and stops, because the design belongs to the consumer. Right\n * for the card; wrong as the place where every entity in an admin app invents\n * its own two-column layout, its own label/value pair and its own ledger.\n *\n * So the four shapes that actually repeat live here, once. Nothing here knows a\n * domain: they take `ReactNode` and lay it out.\n */\n\n/** The expanded body's two-column split: detail on the left, a ledger right. */\nexport function DetailColumns({ left, right }: { left: ReactNode; right: ReactNode }): JSX.Element {\n return (\n <Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', md: '1fr 1fr' }, gap: 3 }}>\n <Box sx={{ minWidth: 0 }}>{left}</Box>\n <Box sx={{ minWidth: 0 }}>{right}</Box>\n </Box>\n );\n}\n\n/**\n * One labelled fact inside an expanded body.\n *\n * Horizontal, not stacked: the body is already a wide area with room for a\n * label beside its value, and stacking them there would ape the summary rails\n * above without their alignment.\n */\nexport function Fact({ label, value }: CardFactProps): JSX.Element {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'space-between', gap: 2, fontSize: 13, py: 0.25 }}>\n <Box component=\"span\" sx={{ color: 'text.secondary', flexShrink: 0 }}>\n {label}\n </Box>\n <Box component=\"span\" sx={{ minWidth: 0, textAlign: 'right', overflowWrap: 'anywhere' }}>\n {value}\n </Box>\n </Box>\n );\n}\n\n/**\n * A money ledger: rows of label/amount, then a ruled total.\n *\n * The total is separated by a RULE rather than by weight alone, because a\n * subtotal and a total in one column with only bold between them is the classic\n * misread — the eye lands on whichever number is larger.\n *\n * The figures arrive pre-formatted. This is a layout, and a component that\n * formatted money would be choosing a locale on the consumer's behalf.\n */\nexport function Ledger({\n lines,\n total,\n}: {\n lines: CardLedgerLine[];\n total: { label: string; value: ReactNode };\n}): JSX.Element {\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.25 }}>\n {lines.map((line) => (\n <Box\n key={line.label}\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n fontSize: 13,\n color: line.tone === 'info' ? 'info.main' : 'text.secondary',\n }}\n >\n <Box component=\"span\">{line.label}</Box>\n <Box component=\"span\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {line.value}\n </Box>\n </Box>\n ))}\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n fontWeight: 700,\n borderTop: 1,\n borderColor: 'divider',\n pt: 0.5,\n mt: 0.5,\n }}\n >\n <Box component=\"span\">{total.label}</Box>\n <Box component=\"span\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {total.value}\n </Box>\n </Box>\n </Box>\n );\n}\n\n/** A heading inside the expanded body, for a section that needs naming. */\nexport function BodyHeading({ children }: { children: ReactNode }): JSX.Element {\n return (\n <Box\n sx={{\n fontSize: 11,\n fontWeight: 700,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n color: 'text.disabled',\n mb: 0.5,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * A wrapping run of small items — permission names, role names, target ids.\n *\n * The whole reason several entities earn a list card at all: a `string[]` has no\n * honest table cell. Truncated to \"3 items\" it says nothing; printed in full it\n * destroys the column. Here it simply wraps.\n */\nexport function TagList({\n items,\n empty,\n}: {\n items: readonly string[];\n /** What to show for an empty run — the consumer's sentence, no default. */\n empty: string;\n}): JSX.Element {\n if (items.length === 0) {\n return <Box sx={{ fontSize: 13, color: 'text.disabled' }}>{empty}</Box>;\n }\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {items.map((item) => (\n <Box\n key={item}\n component=\"span\"\n sx={{\n fontSize: 12,\n px: 0.75,\n py: 0.25,\n borderRadius: 1,\n bgcolor: 'action.hover',\n color: 'text.secondary',\n fontFamily: 'monospace',\n }}\n >\n {item}\n </Box>\n ))}\n </Box>\n );\n}\n","'use client';\n\nimport { useState, type JSX } from 'react';\n\nimport type { ConfirmActionCopy } from '../../../copy';\nimport { ConfirmActionDialog, useConfirmAction } from '../../feedback/ConfirmAction';\n\n/**\n * How the popup should read for the rows about to be acted on.\n *\n * Built from the SELECTION rather than from a single row, because the same\n * guard covers a bulk action: \"Delete 4 categories?\" and \"Delete the category\n * Drinks?\" are the same question asked of a different-sized selection — and an\n * operator who multi-selected by mistake is exactly who this popup is for.\n */\nexport interface RowConfirmCopy {\n title: string;\n description: string;\n /** Echoed into the popup; omit for a multi-row selection the title covers. */\n entityName?: string;\n /** The VERB. Required, never defaulted — see {@link useRowConfirm}. */\n confirmText: string;\n /** Override where the word \"cancel\" would mean the ACTION itself. */\n cancelText?: string;\n /** Require typing this before the confirm enables — for the unrecoverable few. */\n typeToConfirm?: string;\n}\n\ninterface RowConfirmOptions<T> {\n /**\n * The destructive write, over the whole selection. Called ONLY after the\n * operator confirms; throw (or reject) to keep the popup open carrying the\n * message.\n */\n write: (rows: T[]) => Promise<unknown>;\n /** The wording, given the selection. */\n describe: (rows: T[]) => RowConfirmCopy;\n dataTestId: string;\n /** Shown when `write` fails without a message of its own. */\n errorText: string;\n /** The dialog's own words. REQUIRED — this package ships no default copy. */\n copy: ConfirmActionCopy;\n}\n\nexport interface RowConfirm<T> {\n /** Hand this a grid action's `rows`: it opens the popup and writes nothing. */\n request: (rows: T[]) => void;\n /** Render next to the grid. */\n dialog: JSX.Element | null;\n}\n\n/**\n * Confirmation for a grid's `RowAction` — the per-row kebab entry and the\n * multi-select actions menu both, since they run the same handler.\n *\n * The SELECTION is held while the popup is open, so the write sees exactly the\n * rows the operator was looking at when they were asked. Re-reading the grid's\n * live selection at confirm time is the bug this shape avoids: the list can\n * refresh underneath an open dialog.\n *\n * `confirmText` is required and comes from `describe`, with no default. A verb\n * defaulted in the origin's language reads as finished to the next adopter\n * right up until an operator sees it — and `ConfirmOptions` already refuses to\n * default one for the same reason.\n */\nexport function useRowConfirm<T>({\n write,\n describe,\n dataTestId,\n errorText,\n copy,\n}: RowConfirmOptions<T>): RowConfirm<T> {\n const [target, setTarget] = useState<T[] | null>(null);\n\n const state = useConfirmAction(async () => {\n if (!target) return;\n await write(target);\n setTarget(null);\n }, errorText);\n\n const request = (rows: T[]): void => {\n // An empty selection has nothing to confirm — asking would be a popup about\n // nothing, and confirming it would write nothing.\n if (rows.length === 0) return;\n setTarget(rows);\n state.request();\n };\n\n return {\n request,\n dialog: target ? (\n <ConfirmActionDialog state={state}\n copy={copy} {...describe(target)} dataTestId={dataTestId} />\n ) : null,\n };\n}\n","'use client';\n\nimport type { ConfirmActionCopy } from \"../../../copy\";\nimport type { JSX } from 'react';\n\nimport { ConfirmActionDialog, useConfirmAction } from '../../feedback/ConfirmAction';\n\nimport { useCardActions } from './card-actions-context';\n\n/** The `{ ok, error }` envelope a write action answers with. */\nexport interface CardWriteResult {\n ok: boolean;\n error?: string;\n}\n\ninterface RemoveConfirmOptions {\n /** The destructive write. Called ONLY after the operator confirms. */\n write: () => Promise<CardWriteResult>;\n /** The popup's question. */\n title: string;\n /** The row being removed, echoed into the popup so it names a thing. */\n entityName: string;\n /**\n * What happens, and whether it can be walked back. Say which — the difference\n * between a soft delete a recycle bin recovers and one nothing recovers is\n * the whole content of the decision being asked for.\n */\n description: string;\n /** The confirm button's VERB. Required, never defaulted. */\n confirmText: string;\n /** Used when the write fails without a message of its own. */\n fallbackError: string;\n /** The dialog's own words. REQUIRED — this package ships no default copy. */\n copy: ConfirmActionCopy;\n dataTestId: string;\n}\n\ninterface RemoveConfirm {\n /** Hand this to the menu item's `onClick`: it opens the popup, nothing more. */\n request: () => void;\n /** Render alongside the trigger. */\n dialog: JSX.Element;\n}\n\n/**\n * The confirm-before-removing wiring every card/row menu repeats, in one place.\n *\n * It closes the three gaps a hand-rolled version keeps re-opening: the write\n * leaves ONLY on confirm; a refusal is surfaced twice — inside the popup, where\n * the operator is still deciding, and in the shared snackbar behind it — and a\n * failed attempt leaves the popup OPEN to be retried instead of vanishing over\n * a delete that never happened.\n *\n * The difference from {@link useRowConfirm} is which surface it serves: this one\n * is for a SELF-CONTAINED menu that already sits inside a\n * `CardActionsProvider`, so it reads the refresh and the error channel from\n * context and answers the `{ ok, error }` envelope those actions use.\n * `useRowConfirm` is for a grid whose actions are declared as `RowAction[]` and\n * act on a selection.\n *\n * ```tsx\n * const remove = useRemoveConfirm({\n * write: () => deleteCategory({ tenantSlug, id: row.id }),\n * title: copy.deleteTitle,\n * entityName: row.name,\n * description: copy.deleteDescription,\n * confirmText: copy.delete,\n * fallbackError: copy.deleteFailed,\n * dataTestId: 'category-delete-confirm',\n * });\n * ```\n */\nexport function useRemoveConfirm({\n write,\n title,\n entityName,\n description,\n confirmText,\n fallbackError,\n dataTestId,\n copy,\n}: RemoveConfirmOptions): RemoveConfirm {\n const { onRefresh, notifyError } = useCardActions();\n\n const state = useConfirmAction(async () => {\n const result = await write();\n if (!result.ok) {\n const message = result.error ?? fallbackError;\n notifyError(message);\n // Rejecting is what keeps the popup open carrying `message`; the snackbar\n // above is what remains once the operator dismisses it.\n throw new Error(message);\n }\n onRefresh();\n }, fallbackError);\n\n return {\n request: state.request,\n dialog: (\n <ConfirmActionDialog\n state={state}\n copy={copy}\n title={title}\n entityName={entityName}\n description={description}\n confirmText={confirmText}\n dataTestId={dataTestId}\n />\n ),\n };\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","useState","jsx","useState","jsx"]}
|