@mindlogic-ai/logician-ui 5.0.0-alpha.4 → 5.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Form/FormModalFooter/FormModalFooter.d.ts +1 -1
- package/dist/components/Form/FormModalFooter/FormModalFooter.d.ts.map +1 -1
- package/dist/components/Form/FormModalFooter/FormModalFooter.js +2 -2
- package/dist/components/Form/FormModalFooter/FormModalFooter.js.map +1 -1
- package/dist/components/Form/FormModalFooter/FormModalFooter.mjs +2 -2
- package/dist/components/Form/FormModalFooter/FormModalFooter.mjs.map +1 -1
- package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts +7 -0
- package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Form/Form.usage.mdx +3 -1
- package/src/components/Form/FormModalFooter/FormModalFooter.stories.tsx +1 -1
- package/src/components/Form/FormModalFooter/FormModalFooter.test.tsx +19 -1
- package/src/components/Form/FormModalFooter/FormModalFooter.tsx +2 -0
- package/src/components/Form/FormModalFooter/FormModalFooter.types.ts +7 -0
- package/src/foundations/BrandAssets.mdx +637 -0
- package/src/foundations/BrandAssets.stories.tsx +680 -0
|
@@ -15,5 +15,5 @@ import { FormModalFooterProps } from './FormModalFooter.types';
|
|
|
15
15
|
* the logician `ModalFooter`, so callers pin it (`position="sticky"` /
|
|
16
16
|
* `flexShrink={0}`) or zero its padding (`px={0}`) per modal.
|
|
17
17
|
*/
|
|
18
|
-
export declare const FormModalFooter: ({ onDelete, deleteLabel, onCancel, cancelLabel, submitLabel, submitColorPalette, isSubmitting, submitDisabled, onSubmit, bordered, ...rest }: FormModalFooterProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare const FormModalFooter: ({ onDelete, deleteLabel, onCancel, cancelLabel, submitLabel, submitColorPalette, isSubmitting, submitLoadingText, submitDisabled, onSubmit, bordered, ...rest }: FormModalFooterProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
19
|
//# sourceMappingURL=FormModalFooter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormModalFooter.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,GAAI,
|
|
1
|
+
{"version":3,"file":"FormModalFooter.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,GAAI,iKAa7B,oBAAoB,4CAgDtB,CAAC"}
|
|
@@ -40,7 +40,7 @@ require('../../Typography/Text.js');
|
|
|
40
40
|
* the logician `ModalFooter`, so callers pin it (`position="sticky"` /
|
|
41
41
|
* `flexShrink={0}`) or zero its padding (`px={0}`) per modal.
|
|
42
42
|
*/
|
|
43
|
-
const FormModalFooter = ({ onDelete, deleteLabel, onCancel, cancelLabel, submitLabel, submitColorPalette = 'primary', isSubmitting = false, submitDisabled = false, onSubmit, bordered = false, ...rest }) => {
|
|
43
|
+
const FormModalFooter = ({ onDelete, deleteLabel, onCancel, cancelLabel, submitLabel, submitColorPalette = 'primary', isSubmitting = false, submitLoadingText, submitDisabled = false, onSubmit, bordered = false, ...rest }) => {
|
|
44
44
|
return (jsxRuntime.jsxs(ModalFooter.ModalFooter, { justifyContent: "flex-end", gap: 2, ...(bordered
|
|
45
45
|
? {
|
|
46
46
|
bg: 'bg.surface',
|
|
@@ -53,7 +53,7 @@ const FormModalFooter = ({ onDelete, deleteLabel, onCancel, cancelLabel, submitL
|
|
|
53
53
|
, {
|
|
54
54
|
// 5.0 has no colour axis: the deprecated `submitColorPalette` only
|
|
55
55
|
// picks between the two filled roles.
|
|
56
|
-
variant: submitColorPalette === 'danger' ? 'danger' : 'primary', type: onSubmit ? 'button' : 'submit', onClick: onSubmit, loading: isSubmitting, disabled: isSubmitting || submitDisabled, children: submitLabel })] }));
|
|
56
|
+
variant: submitColorPalette === 'danger' ? 'danger' : 'primary', type: onSubmit ? 'button' : 'submit', onClick: onSubmit, loading: isSubmitting, loadingText: submitLoadingText, disabled: isSubmitting || submitDisabled, children: submitLabel })] }));
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
exports.FormModalFooter = FormModalFooter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormModalFooter.js","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.tsx"],"sourcesContent":[null],"names":["_jsxs","ModalFooter","Button","_jsx","TrashIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMA;;;;;;;;;;;;;;;AAeG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAW,EACX,WAAW,EACX,kBAAkB,GAAG,SAAS,EAC9B,YAAY,GAAG,KAAK,EACpB,cAAc,GAAG,KAAK,EACtB,QAAQ,EACR,QAAQ,GAAG,KAAK,EAChB,GAAG,IAAI,EACc,KAAI;AACzB,IAAA,QACEA,eAAA,CAACC,uBAAW,EAAA,EACV,cAAc,EAAC,UAAU,EACzB,GAAG,EAAE,CAAC,EAAA,IACD;AACH,cAAE;AACE,gBAAA,EAAE,EAAE,YAAY;AAChB,gBAAA,SAAS,EAAE,WAAW;AACtB,gBAAA,WAAW,EAAE,eAAe;AAC7B;AACH,cAAE,EAAE,CAAC,EAAA,GACH,IAAI,EAAA,QAAA,EAAA,CAEP,QAAQ,KACPD,eAAA,CAACE,aAAM,EAAA,EACL,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EACtB,EAAE,EAAC,MAAM,EAAA,QAAA,EAAA,CAETC,cAAA,CAACC,eAAS,EAAA,EAAC,OAAO,EAAC,IAAI,EAAA,CAAG,EACzB,WAAW,CAAA,EAAA,CACL,CACV,EACDD,cAAA,CAACD,aAAM,EAAA,EACL,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EAAA,QAAA,EAErB,WAAW,EAAA,CACL,EACTC,eAACD;;;;;;
|
|
1
|
+
{"version":3,"file":"FormModalFooter.js","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.tsx"],"sourcesContent":[null],"names":["_jsxs","ModalFooter","Button","_jsx","TrashIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMA;;;;;;;;;;;;;;;AAeG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAW,EACX,WAAW,EACX,kBAAkB,GAAG,SAAS,EAC9B,YAAY,GAAG,KAAK,EACpB,iBAAiB,EACjB,cAAc,GAAG,KAAK,EACtB,QAAQ,EACR,QAAQ,GAAG,KAAK,EAChB,GAAG,IAAI,EACc,KAAI;AACzB,IAAA,QACEA,eAAA,CAACC,uBAAW,EAAA,EACV,cAAc,EAAC,UAAU,EACzB,GAAG,EAAE,CAAC,EAAA,IACD;AACH,cAAE;AACE,gBAAA,EAAE,EAAE,YAAY;AAChB,gBAAA,SAAS,EAAE,WAAW;AACtB,gBAAA,WAAW,EAAE,eAAe;AAC7B;AACH,cAAE,EAAE,CAAC,EAAA,GACH,IAAI,EAAA,QAAA,EAAA,CAEP,QAAQ,KACPD,eAAA,CAACE,aAAM,EAAA,EACL,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EACtB,EAAE,EAAC,MAAM,EAAA,QAAA,EAAA,CAETC,cAAA,CAACC,eAAS,EAAA,EAAC,OAAO,EAAC,IAAI,EAAA,CAAG,EACzB,WAAW,CAAA,EAAA,CACL,CACV,EACDD,cAAA,CAACD,aAAM,EAAA,EACL,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EAAA,QAAA,EAErB,WAAW,EAAA,CACL,EACTC,eAACD;;;;;;gBAGC,OAAO,EAAE,kBAAkB,KAAK,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAC/D,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACpC,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,iBAAiB,EAC9B,QAAQ,EAAE,YAAY,IAAI,cAAc,YAEvC,WAAW,EAAA,CACL,CAAA,EAAA,CACG;AAElB;;;;"}
|
|
@@ -38,7 +38,7 @@ import '../../Typography/Text.mjs';
|
|
|
38
38
|
* the logician `ModalFooter`, so callers pin it (`position="sticky"` /
|
|
39
39
|
* `flexShrink={0}`) or zero its padding (`px={0}`) per modal.
|
|
40
40
|
*/
|
|
41
|
-
const FormModalFooter = ({ onDelete, deleteLabel, onCancel, cancelLabel, submitLabel, submitColorPalette = 'primary', isSubmitting = false, submitDisabled = false, onSubmit, bordered = false, ...rest }) => {
|
|
41
|
+
const FormModalFooter = ({ onDelete, deleteLabel, onCancel, cancelLabel, submitLabel, submitColorPalette = 'primary', isSubmitting = false, submitLoadingText, submitDisabled = false, onSubmit, bordered = false, ...rest }) => {
|
|
42
42
|
return (jsxs(ModalFooter, { justifyContent: "flex-end", gap: 2, ...(bordered
|
|
43
43
|
? {
|
|
44
44
|
bg: 'bg.surface',
|
|
@@ -51,7 +51,7 @@ const FormModalFooter = ({ onDelete, deleteLabel, onCancel, cancelLabel, submitL
|
|
|
51
51
|
, {
|
|
52
52
|
// 5.0 has no colour axis: the deprecated `submitColorPalette` only
|
|
53
53
|
// picks between the two filled roles.
|
|
54
|
-
variant: submitColorPalette === 'danger' ? 'danger' : 'primary', type: onSubmit ? 'button' : 'submit', onClick: onSubmit, loading: isSubmitting, disabled: isSubmitting || submitDisabled, children: submitLabel })] }));
|
|
54
|
+
variant: submitColorPalette === 'danger' ? 'danger' : 'primary', type: onSubmit ? 'button' : 'submit', onClick: onSubmit, loading: isSubmitting, loadingText: submitLoadingText, disabled: isSubmitting || submitDisabled, children: submitLabel })] }));
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
export { FormModalFooter };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormModalFooter.mjs","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA;;;;;;;;;;;;;;;AAeG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAW,EACX,WAAW,EACX,kBAAkB,GAAG,SAAS,EAC9B,YAAY,GAAG,KAAK,EACpB,cAAc,GAAG,KAAK,EACtB,QAAQ,EACR,QAAQ,GAAG,KAAK,EAChB,GAAG,IAAI,EACc,KAAI;AACzB,IAAA,QACEA,IAAA,CAAC,WAAW,EAAA,EACV,cAAc,EAAC,UAAU,EACzB,GAAG,EAAE,CAAC,EAAA,IACD;AACH,cAAE;AACE,gBAAA,EAAE,EAAE,YAAY;AAChB,gBAAA,SAAS,EAAE,WAAW;AACtB,gBAAA,WAAW,EAAE,eAAe;AAC7B;AACH,cAAE,EAAE,CAAC,EAAA,GACH,IAAI,EAAA,QAAA,EAAA,CAEP,QAAQ,KACPA,IAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EACtB,EAAE,EAAC,MAAM,EAAA,QAAA,EAAA,CAETC,GAAA,CAAC,SAAS,EAAA,EAAC,OAAO,EAAC,IAAI,EAAA,CAAG,EACzB,WAAW,CAAA,EAAA,CACL,CACV,EACDA,GAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EAAA,QAAA,EAErB,WAAW,EAAA,CACL,EACTA,IAAC;;;;;;
|
|
1
|
+
{"version":3,"file":"FormModalFooter.mjs","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA;;;;;;;;;;;;;;;AAeG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAW,EACX,WAAW,EACX,kBAAkB,GAAG,SAAS,EAC9B,YAAY,GAAG,KAAK,EACpB,iBAAiB,EACjB,cAAc,GAAG,KAAK,EACtB,QAAQ,EACR,QAAQ,GAAG,KAAK,EAChB,GAAG,IAAI,EACc,KAAI;AACzB,IAAA,QACEA,IAAA,CAAC,WAAW,EAAA,EACV,cAAc,EAAC,UAAU,EACzB,GAAG,EAAE,CAAC,EAAA,IACD;AACH,cAAE;AACE,gBAAA,EAAE,EAAE,YAAY;AAChB,gBAAA,SAAS,EAAE,WAAW;AACtB,gBAAA,WAAW,EAAE,eAAe;AAC7B;AACH,cAAE,EAAE,CAAC,EAAA,GACH,IAAI,EAAA,QAAA,EAAA,CAEP,QAAQ,KACPA,IAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EACtB,EAAE,EAAC,MAAM,EAAA,QAAA,EAAA,CAETC,GAAA,CAAC,SAAS,EAAA,EAAC,OAAO,EAAC,IAAI,EAAA,CAAG,EACzB,WAAW,CAAA,EAAA,CACL,CACV,EACDA,GAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,EAAA,QAAA,EAErB,WAAW,EAAA,CACL,EACTA,IAAC;;;;;;gBAGC,OAAO,EAAE,kBAAkB,KAAK,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAC/D,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACpC,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,iBAAiB,EAC9B,QAAQ,EAAE,YAAY,IAAI,cAAc,YAEvC,WAAW,EAAA,CACL,CAAA,EAAA,CACG;AAElB;;;;"}
|
|
@@ -29,6 +29,13 @@ export interface FormModalFooterProps extends Omit<ModalFooterProps, 'children'
|
|
|
29
29
|
* modal can't be dismissed or re-submitted mid-request.
|
|
30
30
|
*/
|
|
31
31
|
isSubmitting?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* What the submit button says while `isSubmitting`, as a short present-tense
|
|
34
|
+
* state ("Saving", "저장 중"). Forwarded to the Button's `loadingText`, so the
|
|
35
|
+
* busy button keeps a name instead of becoming a bare spinner (Button usage:
|
|
36
|
+
* `loading` needs `loadingText`). The app owns the copy, like every label here.
|
|
37
|
+
*/
|
|
38
|
+
submitLoadingText?: ReactNode;
|
|
32
39
|
/**
|
|
33
40
|
* Extra disable condition for the primary button beyond `isSubmitting` — a
|
|
34
41
|
* pristine/invalid gate (e.g. `!name.trim()`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormModalFooter.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,KAAK,gBAAgB,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC;AAE3D,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,gBAAgB,EAChB,UAAU,GAAG,UAAU,GAAG,OAAO,CAClC;IACC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,SAAS,CAAC;IACvB,mCAAmC;IACnC,WAAW,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
|
|
1
|
+
{"version":3,"file":"FormModalFooter.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/FormModalFooter/FormModalFooter.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,KAAK,gBAAgB,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC;AAE3D,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,gBAAgB,EAChB,UAAU,GAAG,UAAU,GAAG,OAAO,CAClC;IACC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,SAAS,CAAC;IACvB,mCAAmC;IACnC,WAAW,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
|
package/package.json
CHANGED
|
@@ -121,7 +121,8 @@ What these parts do for you:
|
|
|
121
121
|
- `FormModalFooter` keeps the submit a `type="submit"` button inside a
|
|
122
122
|
`<form>`, so Enter submits; pass `onSubmit` only for a portalled or
|
|
123
123
|
form-less modal. `isSubmitting` disables every button so the modal cannot be
|
|
124
|
-
dismissed mid-request.
|
|
124
|
+
dismissed mid-request. Pair it with `submitLoadingText` ("Saving") so the
|
|
125
|
+
busy submit button still says what it is doing.
|
|
125
126
|
- A collapsed `FormSection` with `hasError` swaps its chevron for a danger
|
|
126
127
|
glyph, so hidden errors are not missed.
|
|
127
128
|
|
|
@@ -172,6 +173,7 @@ top rule, `FormSection` `divider` uses `border.subtle`, and `FieldError` uses
|
|
|
172
173
|
- `FormModalFooter`는 `<form>` 안에서 제출 버튼을 `type="submit"`으로 두어 Enter로
|
|
173
174
|
제출되게 합니다. `onSubmit`은 포털로 그려지거나 `<form>`이 없는 모달에서만 넘깁니다.
|
|
174
175
|
`isSubmitting`이면 모든 버튼이 비활성이 되어 요청 중에 모달이 닫히지 않습니다.
|
|
176
|
+
`submitLoadingText`("저장 중")를 함께 넘기면 요청 중인 제출 버튼도 무엇을 하는지 말합니다.
|
|
175
177
|
- `hasError`인 `FormSection`이 접혀 있으면 펼침 화살표 대신 위험 표시가 보여 숨은
|
|
176
178
|
오류를 놓치지 않습니다.
|
|
177
179
|
|
|
@@ -50,7 +50,7 @@ export const WithDelete: Story = {
|
|
|
50
50
|
|
|
51
51
|
/** Mid-request: spinner on submit, every button disabled. */
|
|
52
52
|
export const Submitting: Story = {
|
|
53
|
-
args: { isSubmitting: true },
|
|
53
|
+
args: { isSubmitting: true, submitLoadingText: 'Saving' },
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
/** Gated submit (e.g. a required field is empty). */
|
|
@@ -20,12 +20,14 @@ vi.mock('@/components/Button', () => ({
|
|
|
20
20
|
type,
|
|
21
21
|
disabled,
|
|
22
22
|
loading,
|
|
23
|
+
loadingText,
|
|
23
24
|
}: {
|
|
24
25
|
children?: ReactNode;
|
|
25
26
|
onClick?: () => void;
|
|
26
27
|
type?: 'button' | 'submit';
|
|
27
28
|
disabled?: boolean;
|
|
28
29
|
loading?: boolean;
|
|
30
|
+
loadingText?: ReactNode;
|
|
29
31
|
}) => (
|
|
30
32
|
<button
|
|
31
33
|
type={type}
|
|
@@ -33,7 +35,7 @@ vi.mock('@/components/Button', () => ({
|
|
|
33
35
|
disabled={disabled}
|
|
34
36
|
data-loading={loading ? 'true' : 'false'}
|
|
35
37
|
>
|
|
36
|
-
{children}
|
|
38
|
+
{loading && loadingText ? loadingText : children}
|
|
37
39
|
</button>
|
|
38
40
|
),
|
|
39
41
|
}));
|
|
@@ -139,6 +141,22 @@ describe('FormModalFooter', () => {
|
|
|
139
141
|
expect(submit).toHaveAttribute('data-loading', 'true');
|
|
140
142
|
});
|
|
141
143
|
|
|
144
|
+
it('names the busy submit button with submitLoadingText', () => {
|
|
145
|
+
render(
|
|
146
|
+
<FormModalFooter
|
|
147
|
+
onCancel={noop}
|
|
148
|
+
onSubmit={noop}
|
|
149
|
+
cancelLabel="Cancel"
|
|
150
|
+
submitLabel="Save"
|
|
151
|
+
submitLoadingText="Saving"
|
|
152
|
+
isSubmitting
|
|
153
|
+
/>
|
|
154
|
+
);
|
|
155
|
+
const submit = screen.getByRole('button', { name: 'Saving' });
|
|
156
|
+
expect(submit).toBeDisabled();
|
|
157
|
+
expect(submit).toHaveAttribute('data-loading', 'true');
|
|
158
|
+
});
|
|
159
|
+
|
|
142
160
|
it('disables only the submit button when submitDisabled is set', () => {
|
|
143
161
|
render(
|
|
144
162
|
<FormModalFooter
|
|
@@ -28,6 +28,7 @@ export const FormModalFooter = ({
|
|
|
28
28
|
submitLabel,
|
|
29
29
|
submitColorPalette = 'primary',
|
|
30
30
|
isSubmitting = false,
|
|
31
|
+
submitLoadingText,
|
|
31
32
|
submitDisabled = false,
|
|
32
33
|
onSubmit,
|
|
33
34
|
bordered = false,
|
|
@@ -73,6 +74,7 @@ export const FormModalFooter = ({
|
|
|
73
74
|
type={onSubmit ? 'button' : 'submit'}
|
|
74
75
|
onClick={onSubmit}
|
|
75
76
|
loading={isSubmitting}
|
|
77
|
+
loadingText={submitLoadingText}
|
|
76
78
|
disabled={isSubmitting || submitDisabled}
|
|
77
79
|
>
|
|
78
80
|
{submitLabel}
|
|
@@ -35,6 +35,13 @@ export interface FormModalFooterProps extends Omit<
|
|
|
35
35
|
* modal can't be dismissed or re-submitted mid-request.
|
|
36
36
|
*/
|
|
37
37
|
isSubmitting?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* What the submit button says while `isSubmitting`, as a short present-tense
|
|
40
|
+
* state ("Saving", "저장 중"). Forwarded to the Button's `loadingText`, so the
|
|
41
|
+
* busy button keeps a name instead of becoming a bare spinner (Button usage:
|
|
42
|
+
* `loading` needs `loadingText`). The app owns the copy, like every label here.
|
|
43
|
+
*/
|
|
44
|
+
submitLoadingText?: ReactNode;
|
|
38
45
|
/**
|
|
39
46
|
* Extra disable condition for the primary button beyond `isSubmitting` — a
|
|
40
47
|
* pristine/invalid gate (e.g. `!name.trim()`).
|