@lerianstudio/sindarian-ui 1.4.0-beta.8 → 2.0.0-beta.2
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/card/account-card/index.d.ts.map +1 -1
- package/dist/components/card/account-card/index.js +1 -1
- package/dist/components/card/entity-card/index.js +3 -3
- package/dist/components/dialog/confirmation-dialog/index.d.ts +36 -5
- package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
- package/dist/components/dialog/confirmation-dialog/index.js +2 -2
- package/dist/components/entity-box/index.js +1 -1
- package/dist/components/entity-data-table/index.d.ts.map +1 -1
- package/dist/components/entity-data-table/index.js +1 -1
- package/dist/components/form/file-upload-field/index.d.ts +11 -2
- package/dist/components/form/file-upload-field/index.d.ts.map +1 -1
- package/dist/components/form/file-upload-field/index.js +8 -3
- package/dist/components/form/input-field/index.d.ts +41 -2
- package/dist/components/form/input-field/index.d.ts.map +1 -1
- package/dist/components/form/input-field/index.js +73 -15
- package/dist/components/form/select-field/index.d.ts +9 -1
- package/dist/components/form/select-field/index.d.ts.map +1 -1
- package/dist/components/form/select-field/index.js +2 -2
- package/dist/components/page-header/index.d.ts.map +1 -1
- package/dist/components/page-header/index.js +2 -2
- package/dist/components/ui/autocomplete/index.d.ts +34 -6
- package/dist/components/ui/autocomplete/index.d.ts.map +1 -1
- package/dist/components/ui/autocomplete/index.js +72 -16
- package/dist/components/ui/badge/index.d.ts.map +1 -1
- package/dist/components/ui/badge/index.js +11 -1
- package/dist/components/ui/button/styles.css +31 -1
- package/dist/components/ui/calendar/index.d.ts.map +1 -1
- package/dist/components/ui/calendar/index.js +7 -1
- package/dist/components/ui/card/index.d.ts.map +1 -1
- package/dist/components/ui/card/index.js +1 -1
- package/dist/components/ui/dropdown-menu/index.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu/index.js +4 -1
- package/dist/components/ui/field/index.d.ts.map +1 -1
- package/dist/components/ui/field/index.js +5 -2
- package/dist/components/ui/file-upload/index.d.ts +76 -9
- package/dist/components/ui/file-upload/index.d.ts.map +1 -1
- package/dist/components/ui/file-upload/index.js +47 -12
- package/dist/components/ui/form.d.ts +4 -0
- package/dist/components/ui/form.d.ts.map +1 -1
- package/dist/components/ui/form.js +53 -8
- package/dist/components/ui/multiple-select/index.js +2 -2
- package/dist/components/ui/progress/index.d.ts +15 -1
- package/dist/components/ui/progress/index.d.ts.map +1 -1
- package/dist/components/ui/progress/index.js +25 -2
- package/dist/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
- package/dist/components/ui/sidebar/sidebar-expand-button.js +17 -1
- package/dist/components/ui/toggle-group/index.d.ts +1 -1
- package/dist/components/ui/toggle-group/index.d.ts.map +1 -1
- package/dist/components/ui/toggle-group/index.js +73 -4
- package/dist/components/ui/tooltip/index.d.ts +15 -0
- package/dist/components/ui/tooltip/index.d.ts.map +1 -1
- package/dist/components/ui/tooltip/index.js +16 -1
- package/dist/domain/blotter/index.d.ts +4 -2
- package/dist/domain/blotter/index.d.ts.map +1 -1
- package/dist/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
- package/dist/domain/delinquency-aging/aging-buckets.js +8 -3
- package/dist/domain/delinquency-aging/index.d.ts.map +1 -1
- package/dist/domain/delinquency-aging/index.js +8 -3
- package/dist/domain/key-id/index.js +1 -1
- package/dist/domain/status-rail/index.js +1 -1
- package/dist/domain/threshold-gauge/index.d.ts.map +1 -1
- package/dist/domain/threshold-gauge/index.js +9 -5
- package/dist/enterprise/stat-card/index.d.ts.map +1 -1
- package/dist/enterprise/stat-card/index.js +12 -4
- package/dist/esm/components/card/account-card/index.d.ts.map +1 -1
- package/dist/esm/components/card/account-card/index.js +1 -1
- package/dist/esm/components/card/entity-card/index.js +3 -3
- package/dist/esm/components/dialog/confirmation-dialog/index.d.ts +36 -5
- package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
- package/dist/esm/components/dialog/confirmation-dialog/index.js +2 -2
- package/dist/esm/components/entity-box/index.js +1 -1
- package/dist/esm/components/entity-data-table/index.d.ts.map +1 -1
- package/dist/esm/components/entity-data-table/index.js +1 -1
- package/dist/esm/components/form/file-upload-field/index.d.ts +11 -2
- package/dist/esm/components/form/file-upload-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/file-upload-field/index.js +8 -3
- package/dist/esm/components/form/input-field/index.d.ts +41 -2
- package/dist/esm/components/form/input-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/input-field/index.js +73 -15
- package/dist/esm/components/form/select-field/index.d.ts +9 -1
- package/dist/esm/components/form/select-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/select-field/index.js +2 -2
- package/dist/esm/components/page-header/index.d.ts.map +1 -1
- package/dist/esm/components/page-header/index.js +2 -2
- package/dist/esm/components/ui/autocomplete/index.d.ts +34 -6
- package/dist/esm/components/ui/autocomplete/index.d.ts.map +1 -1
- package/dist/esm/components/ui/autocomplete/index.js +72 -16
- package/dist/esm/components/ui/badge/index.d.ts.map +1 -1
- package/dist/esm/components/ui/badge/index.js +11 -1
- package/dist/esm/components/ui/calendar/index.d.ts.map +1 -1
- package/dist/esm/components/ui/calendar/index.js +8 -2
- package/dist/esm/components/ui/card/index.d.ts.map +1 -1
- package/dist/esm/components/ui/card/index.js +1 -1
- package/dist/esm/components/ui/dropdown-menu/index.d.ts.map +1 -1
- package/dist/esm/components/ui/dropdown-menu/index.js +4 -1
- package/dist/esm/components/ui/field/index.d.ts.map +1 -1
- package/dist/esm/components/ui/field/index.js +5 -2
- package/dist/esm/components/ui/file-upload/index.d.ts +76 -9
- package/dist/esm/components/ui/file-upload/index.d.ts.map +1 -1
- package/dist/esm/components/ui/file-upload/index.js +47 -13
- package/dist/esm/components/ui/form.d.ts +4 -0
- package/dist/esm/components/ui/form.d.ts.map +1 -1
- package/dist/esm/components/ui/form.js +53 -8
- package/dist/esm/components/ui/multiple-select/index.js +2 -2
- package/dist/esm/components/ui/progress/index.d.ts +15 -1
- package/dist/esm/components/ui/progress/index.d.ts.map +1 -1
- package/dist/esm/components/ui/progress/index.js +25 -2
- package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +17 -1
- package/dist/esm/components/ui/toggle-group/index.d.ts +1 -1
- package/dist/esm/components/ui/toggle-group/index.d.ts.map +1 -1
- package/dist/esm/components/ui/toggle-group/index.js +73 -4
- package/dist/esm/components/ui/tooltip/index.d.ts +15 -0
- package/dist/esm/components/ui/tooltip/index.d.ts.map +1 -1
- package/dist/esm/components/ui/tooltip/index.js +16 -1
- package/dist/esm/domain/blotter/index.d.ts +4 -2
- package/dist/esm/domain/blotter/index.d.ts.map +1 -1
- package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
- package/dist/esm/domain/delinquency-aging/aging-buckets.js +8 -3
- package/dist/esm/domain/delinquency-aging/index.d.ts.map +1 -1
- package/dist/esm/domain/delinquency-aging/index.js +8 -3
- package/dist/esm/domain/key-id/index.js +1 -1
- package/dist/esm/domain/status-rail/index.js +1 -1
- package/dist/esm/domain/threshold-gauge/index.d.ts.map +1 -1
- package/dist/esm/domain/threshold-gauge/index.js +9 -5
- package/dist/esm/enterprise/stat-card/index.d.ts.map +1 -1
- package/dist/esm/enterprise/stat-card/index.js +12 -4
- package/dist/globals.css +24 -1
- package/package.json +1 -1
|
@@ -23,7 +23,7 @@ const useFormField = () => {
|
|
|
23
23
|
const fieldState = form && fieldContext.name
|
|
24
24
|
? form.getFieldState(fieldContext.name, form.formState)
|
|
25
25
|
: undefined;
|
|
26
|
-
const { id, required } = itemContext;
|
|
26
|
+
const { id, required, described, onDescribedChange } = itemContext;
|
|
27
27
|
return {
|
|
28
28
|
id,
|
|
29
29
|
name: fieldContext.name,
|
|
@@ -31,36 +31,81 @@ const useFormField = () => {
|
|
|
31
31
|
formDescriptionId: `${id}-form-item-description`,
|
|
32
32
|
formMessageId: `${id}-form-item-message`,
|
|
33
33
|
required,
|
|
34
|
+
described,
|
|
35
|
+
onDescribedChange,
|
|
34
36
|
...fieldState
|
|
35
37
|
};
|
|
36
38
|
};
|
|
37
39
|
const FormItemContext = React.createContext({});
|
|
40
|
+
/**
|
|
41
|
+
* Announce that this slot is on the page, for as long as it is.
|
|
42
|
+
*
|
|
43
|
+
* `rendered` is a parameter rather than a caller-side condition because
|
|
44
|
+
* `FormMessage` returns null when it has nothing to say, and a hook cannot sit
|
|
45
|
+
* behind that early return.
|
|
46
|
+
*/
|
|
47
|
+
function useDescribingSlot(slot, rendered) {
|
|
48
|
+
const { onDescribedChange } = React.useContext(FormItemContext);
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
if (!rendered)
|
|
51
|
+
return;
|
|
52
|
+
onDescribedChange?.(slot, true);
|
|
53
|
+
return () => onDescribedChange?.(slot, false);
|
|
54
|
+
}, [onDescribedChange, slot, rendered]);
|
|
55
|
+
}
|
|
38
56
|
const FormItem = React.forwardRef(({ className, required, ...props }, ref) => {
|
|
39
57
|
const id = React.useId();
|
|
40
|
-
|
|
58
|
+
const [described, setDescribed] = React.useState({ message: false, description: false });
|
|
59
|
+
// Keeps the object identity when nothing moved, so a slot re-registering
|
|
60
|
+
// does not re-render the item for no reason.
|
|
61
|
+
const onDescribedChange = React.useCallback((slot, rendered) => setDescribed((current) => current[slot] === rendered
|
|
62
|
+
? current
|
|
63
|
+
: { ...current, [slot]: rendered }), []);
|
|
64
|
+
return (_jsx(FormItemContext.Provider, { value: { id, required, described, onDescribedChange }, children: _jsx("div", { ref: ref, className: cn('space-y-2', className), ...props }) }));
|
|
41
65
|
});
|
|
42
66
|
FormItem.displayName = 'FormItem';
|
|
43
67
|
const FormLabel = React.forwardRef(({ className, extra, children, ...props }, ref) => {
|
|
44
68
|
const { required, error, formItemId } = useFormField();
|
|
45
|
-
return (_jsxs(Label, { ref: ref, className: cn('text-muted-foreground flex justify-between text-sm font-semibold',
|
|
69
|
+
return (_jsxs(Label, { ref: ref, className: cn('text-muted-foreground flex justify-between text-sm font-semibold',
|
|
70
|
+
// The error TEXT token, matching FormMessage below: `--destructive`
|
|
71
|
+
// is the badge/fill family and reads 3.80:1 as ink on the dark card.
|
|
72
|
+
error && 'text-system-error-h1a', className), htmlFor: formItemId, ...props, children: [_jsxs("span", { children: [children, required ? ' *' : ''] }), extra] }));
|
|
46
73
|
});
|
|
47
74
|
FormLabel.displayName = 'FormLabel';
|
|
48
75
|
export const FormTooltip = ({ children, ...others }) => (_jsx(TooltipProvider, { ...others, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(HelpCircle, { className: "text-container-text ml-2 h-4 w-4" }) }), _jsx(TooltipContent, { children: children })] }) }));
|
|
49
76
|
const FormControl = React.forwardRef(({ ...props }, ref) => {
|
|
50
|
-
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
77
|
+
const { error, formItemId, formDescriptionId, formMessageId, described } = useFormField();
|
|
78
|
+
// Only ids that resolve. A screen reader drops a dangling IDREF silently, so
|
|
79
|
+
// the barrier this removes is diagnostic rather than operational: a form with
|
|
80
|
+
// thirteen broken associations is a form where a real one cannot be spotted.
|
|
81
|
+
//
|
|
82
|
+
// Message first: a reader hears the error before the hint. `undefined` when
|
|
83
|
+
// both slots are empty, which drops the attribute — and, because Radix Slot
|
|
84
|
+
// OVERWRITES rather than merges, still lets the wrapped element carry its own
|
|
85
|
+
// (`ui/file-upload` merges the injected id with its own error id that way).
|
|
86
|
+
const describedBy = [
|
|
87
|
+
described?.message ? formMessageId : undefined,
|
|
88
|
+
described?.description ? formDescriptionId : undefined
|
|
89
|
+
]
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
.join(' ') || undefined;
|
|
92
|
+
return (_jsx(Slot, { ref: ref, id: formItemId, "aria-describedby": describedBy, "aria-invalid": !!error, ...props }));
|
|
54
93
|
});
|
|
55
94
|
FormControl.displayName = 'FormControl';
|
|
56
95
|
const FormDescription = React.forwardRef(({ className, ...props }, ref) => {
|
|
57
96
|
const { formDescriptionId } = useFormField();
|
|
58
|
-
|
|
97
|
+
useDescribingSlot('description', true);
|
|
98
|
+
return (_jsx("p", { ref: ref, id: formDescriptionId, className: cn('text-muted-foreground text-xs font-medium', className), ...props }));
|
|
59
99
|
});
|
|
60
100
|
FormDescription.displayName = 'FormDescription';
|
|
61
101
|
const FormMessage = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
62
102
|
const { error, formMessageId } = useFormField();
|
|
63
103
|
const body = error ? String(error?.message) : children;
|
|
104
|
+
// Registered on `body`, not on `error`: a message given plain children
|
|
105
|
+
// renders copy that the control has to point at too. The old expression only
|
|
106
|
+
// added the message id when react-hook-form reported an error, so a
|
|
107
|
+
// standalone message was rendered and never associated.
|
|
108
|
+
useDescribingSlot('message', Boolean(body));
|
|
64
109
|
if (!body) {
|
|
65
110
|
return null;
|
|
66
111
|
}
|
|
@@ -38,7 +38,7 @@ export const MultipleSelectTrigger = React.forwardRef(({ className, children, re
|
|
|
38
38
|
setOpen(false);
|
|
39
39
|
inputRef.current?.blur();
|
|
40
40
|
});
|
|
41
|
-
return (_jsxs("div", { ref: _ref, className: cn('bg-background ring-offset-background placeholder:text-
|
|
41
|
+
return (_jsxs("div", { ref: _ref, className: cn('bg-background ring-offset-background placeholder:text-input-placeholder focus:ring-ring border-input-border flex flex-row rounded-md border text-sm focus:ring-2 focus:ring-offset-0 focus:outline-hidden focus-visible:outline-hidden md:text-sm [&>span]:line-clamp-1', {
|
|
42
42
|
'h-10': value.length === 0,
|
|
43
43
|
'min-h-10': value.length > 0,
|
|
44
44
|
'cursor-text': !disabled && !readOnly && value.length !== 0,
|
|
@@ -77,7 +77,7 @@ export const MultipleSelectValue = React.forwardRef(({ className, ...props }, re
|
|
|
77
77
|
value?.map((value) => (_jsxs(Badge, { variant: "secondary", className: cn('data-disabled:bg-muted-foreground data-fixed:bg-muted-foreground data-disabled:text-muted data-fixed:text-muted data-disabled:hover:bg-muted-foreground data-fixed:hover:bg-muted-foreground'), children: [showValue ? value : options[value], _jsx("button", { type: "button", className: cn('ring-offset-background focus:ring-ring ml-1 rounded-full outline-hidden focus:ring-2 focus:ring-offset-2', disabled && 'hidden'), children: _jsx(X, { className: "text-muted-foreground hover:text-foreground h-3 w-3", onClick: (event) => {
|
|
78
78
|
event.stopPropagation();
|
|
79
79
|
handleChange(value);
|
|
80
|
-
} }) })] }, value))), _jsx(CommandPrimitive.Input, { ...props, ref: inputRef, disabled: disabled, className: cn('placeholder:text-
|
|
80
|
+
} }) })] }, value))), _jsx(CommandPrimitive.Input, { ...props, ref: inputRef, disabled: disabled, className: cn('placeholder:text-input-placeholder bg-transparent outline-hidden focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 disabled:placeholder:opacity-0', className) })] }));
|
|
81
81
|
});
|
|
82
82
|
MultipleSelectValue.displayName = 'MultipleSelectValue';
|
|
83
83
|
export const MultipleSelectEmpty = React.forwardRef(({ className, ...props }, forwardedRef) => {
|
|
@@ -3,6 +3,20 @@ import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
|
3
3
|
type ProgressProps = React.ComponentProps<typeof ProgressPrimitive.Root> & {
|
|
4
4
|
indicatorColor?: string;
|
|
5
5
|
};
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* `value` and `max` are Radix's own props, so the bar reports `aria-valuenow` /
|
|
8
|
+
* `aria-valuemax` and flips `data-state` between `loading` and `complete`.
|
|
9
|
+
* Omitting `value`, or passing `null`, is Radix's indeterminate state and draws
|
|
10
|
+
* an empty track.
|
|
11
|
+
*
|
|
12
|
+
* Both numbers are BOUNDED BEFORE THE ROOT SEES THEM, so the drawn width and
|
|
13
|
+
* the announced value can never disagree. Radix accepts a value only inside
|
|
14
|
+
* `[0, max]`: hand it one outside and the root drops `aria-valuenow`, sticks
|
|
15
|
+
* `data-state` on `indeterminate` and logs an error, while the indicator here
|
|
16
|
+
* goes on drawing the clamped bar. Substituting 100 for a non-positive max is
|
|
17
|
+
* Radix's own fallback, and is also what keeps a `max` of 0 from dividing by
|
|
18
|
+
* zero.
|
|
19
|
+
*/
|
|
20
|
+
declare function Progress({ className, value, max, indicatorColor, ...props }: ProgressProps): React.JSX.Element;
|
|
7
21
|
export { Progress };
|
|
8
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/progress/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAI7D,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,GAAG;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,cAA6B,EAC7B,GAAG,KAAK,EACT,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/progress/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAI7D,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,GAAG;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,GAAG,EACH,cAA6B,EAC7B,GAAG,KAAK,EACT,EAAE,aAAa,qBA6Bf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -2,7 +2,30 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
4
4
|
import { cn } from '../../../lib/utils.js';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* `value` and `max` are Radix's own props, so the bar reports `aria-valuenow` /
|
|
7
|
+
* `aria-valuemax` and flips `data-state` between `loading` and `complete`.
|
|
8
|
+
* Omitting `value`, or passing `null`, is Radix's indeterminate state and draws
|
|
9
|
+
* an empty track.
|
|
10
|
+
*
|
|
11
|
+
* Both numbers are BOUNDED BEFORE THE ROOT SEES THEM, so the drawn width and
|
|
12
|
+
* the announced value can never disagree. Radix accepts a value only inside
|
|
13
|
+
* `[0, max]`: hand it one outside and the root drops `aria-valuenow`, sticks
|
|
14
|
+
* `data-state` on `indeterminate` and logs an error, while the indicator here
|
|
15
|
+
* goes on drawing the clamped bar. Substituting 100 for a non-positive max is
|
|
16
|
+
* Radix's own fallback, and is also what keeps a `max` of 0 from dividing by
|
|
17
|
+
* zero.
|
|
18
|
+
*/
|
|
19
|
+
function Progress({ className, value, max, indicatorColor = 'bg-primary', ...props }) {
|
|
20
|
+
const scale = Number.isFinite(max) && max > 0 ? max : 100;
|
|
21
|
+
// Bound against `scale`, not against the rejected `max`: with `max={0}` the
|
|
22
|
+
// scale is already 100, and clamping to 0 would report a finished bar empty.
|
|
23
|
+
// Non-finite values are indeterminate, matching Radix without producing an
|
|
24
|
+
// invalid CSS transform.
|
|
25
|
+
const bounded = Number.isFinite(value)
|
|
26
|
+
? Math.min(scale, Math.max(0, value))
|
|
27
|
+
: null;
|
|
28
|
+
const percent = ((bounded ?? 0) / scale) * 100;
|
|
29
|
+
return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", value: bounded, max: scale, className: cn('bg-primary/20 relative h-4 w-full overflow-hidden rounded-full', className), ...props, children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: cn('h-full w-full flex-1 transition-all', indicatorColor), style: { transform: `translateX(-${100 - percent}%)` } }) }));
|
|
7
30
|
}
|
|
8
31
|
export { Progress };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar-expand-button.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/sidebar/sidebar-expand-button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,KAAK,wBAAwB,GAAG;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,aAAa,wBAAwB,
|
|
1
|
+
{"version":3,"file":"sidebar-expand-button.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/sidebar/sidebar-expand-button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,KAAK,wBAAwB,GAAG;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,aAAa,wBAAwB,sBAyDxE,CAAA"}
|
|
@@ -8,5 +8,21 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../
|
|
|
8
8
|
import { IconButton } from '../icon-button/index.js';
|
|
9
9
|
export const SidebarExpandButton = ({ tooltip }) => {
|
|
10
10
|
const { isCollapsed, toggleSidebar } = useSidebar();
|
|
11
|
-
return (_jsxs(React.Fragment, { children: [!isCollapsed && (_jsx("div", { "data-slot": "sidebar-expand-button", className: "border-border bg-card flex w-full", children: _jsx("div", { className: "absolute right-[-20px] bottom-4", children: _jsx(IconButton, { variant: "secondary", rounded: true, onClick: toggleSidebar, "aria-label": tooltip || 'Collapse sidebar', "aria-expanded": true, children: _jsx(PanelLeftClose, { className: "text-
|
|
11
|
+
return (_jsxs(React.Fragment, { children: [!isCollapsed && (_jsx("div", { "data-slot": "sidebar-expand-button", className: "border-border bg-card flex w-full", children: _jsx("div", { className: "absolute right-[-20px] bottom-4", children: _jsx(IconButton, { variant: "secondary", rounded: true, onClick: toggleSidebar, "aria-label": tooltip || 'Collapse sidebar', "aria-expanded": true, children: _jsx(PanelLeftClose, { className: "text-muted-foreground" }) }) }) })), isCollapsed && (_jsx(SidebarFooter, { children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger
|
|
12
|
+
// `hover:text-accent-foreground` on the TRIGGER, not only on
|
|
13
|
+
// the glyph below. The base ink here used to be base/400, which
|
|
14
|
+
// no rule paired with anything; now that it is the muted token,
|
|
15
|
+
// it is the ink anything inside this trigger inherits, and the
|
|
16
|
+
// muted token reads 1.07:1 on sunglow in dark. The glyph
|
|
17
|
+
// overrides it today, so this pairs the fill for whatever the
|
|
18
|
+
// trigger holds next.
|
|
19
|
+
, {
|
|
20
|
+
// `hover:text-accent-foreground` on the TRIGGER, not only on
|
|
21
|
+
// the glyph below. The base ink here used to be base/400, which
|
|
22
|
+
// no rule paired with anything; now that it is the muted token,
|
|
23
|
+
// it is the ink anything inside this trigger inherits, and the
|
|
24
|
+
// muted token reads 1.07:1 on sunglow in dark. The glyph
|
|
25
|
+
// overrides it today, so this pairs the fill for whatever the
|
|
26
|
+
// trigger holds next.
|
|
27
|
+
className: "group/expand-button text-muted-foreground hover:bg-accent hover:text-accent-foreground rounded-sm bg-transparent p-2", onClick: toggleSidebar, "aria-label": tooltip || 'Expand sidebar', "aria-expanded": false, children: _jsx(PanelRightClose, { className: "group-hover/expand-button:text-accent-foreground dark:text-white" }) }), _jsx(TooltipContent, { side: "right", children: tooltip || 'Expand' })] }) }) }))] }));
|
|
12
28
|
};
|
|
@@ -13,6 +13,6 @@ declare const toggleVariants: (props?: ({
|
|
|
13
13
|
declare function ToggleGroup({ className, variant, size, spacing, children, style, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants> & {
|
|
14
14
|
spacing?: number;
|
|
15
15
|
}): React.JSX.Element;
|
|
16
|
-
declare function ToggleGroupItem({ className, children, variant, size, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>): React.JSX.Element;
|
|
16
|
+
declare function ToggleGroupItem({ className, children, variant, size, onFocus, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>): React.JSX.Element;
|
|
17
17
|
export { ToggleGroup, ToggleGroupItem };
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/toggle-group/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,oBAAoB,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE;;;;GAIG;AACH,QAAA,MAAM,cAAc;;;8EAoBnB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/toggle-group/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,oBAAoB,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE;;;;GAIG;AACH,QAAA,MAAM,cAAc;;;8EAoBnB,CAAA;AA4DD,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAW,EACX,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,GACvD,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,qBA+BF;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,OAAO,EACP,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,GACvD,YAAY,CAAC,OAAO,cAAc,CAAC,qBAiDpC;AAED,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -26,12 +26,58 @@ const toggleVariants = cva("hover:bg-muted hover:text-muted-foreground focus-vis
|
|
|
26
26
|
size: 'default'
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
|
+
const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
|
|
30
|
+
/**
|
|
31
|
+
* Is an arrow key down right now?
|
|
32
|
+
*
|
|
33
|
+
* This is how an item tells keyboard navigation apart from a pointer press or a
|
|
34
|
+
* programmatic focus, and it is the seam Radix uses for the same job in its own
|
|
35
|
+
* `RadioGroup`. It works because `RovingFocusGroup` defers the focus move to a
|
|
36
|
+
* `setTimeout`: the keydown has already bubbled to `document` and set the flag
|
|
37
|
+
* by the time the item receives `focus`.
|
|
38
|
+
*
|
|
39
|
+
* The distinction is not cosmetic. A pointer press focuses BEFORE the click
|
|
40
|
+
* lands, so selecting on every focus would turn one click into
|
|
41
|
+
* select-then-deselect and break mouse selection outright.
|
|
42
|
+
*
|
|
43
|
+
* Returns null when disabled, so `type="multiple"` carries no flag to read.
|
|
44
|
+
*/
|
|
45
|
+
function useArrowKeyPressed(enabled) {
|
|
46
|
+
const arrowKeyPressed = React.useRef(false);
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
if (!enabled)
|
|
49
|
+
return;
|
|
50
|
+
const onKeyDown = (event) => {
|
|
51
|
+
if (ARROW_KEYS.includes(event.key))
|
|
52
|
+
arrowKeyPressed.current = true;
|
|
53
|
+
};
|
|
54
|
+
const onKeyUp = () => {
|
|
55
|
+
arrowKeyPressed.current = false;
|
|
56
|
+
};
|
|
57
|
+
document.addEventListener('keydown', onKeyDown);
|
|
58
|
+
document.addEventListener('keyup', onKeyUp);
|
|
59
|
+
window.addEventListener('blur', onKeyUp);
|
|
60
|
+
return () => {
|
|
61
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
62
|
+
document.removeEventListener('keyup', onKeyUp);
|
|
63
|
+
window.removeEventListener('blur', onKeyUp);
|
|
64
|
+
// A group unmounted mid-keystroke never sees the keyup.
|
|
65
|
+
arrowKeyPressed.current = false;
|
|
66
|
+
};
|
|
67
|
+
}, [enabled]);
|
|
68
|
+
return enabled ? arrowKeyPressed : null;
|
|
69
|
+
}
|
|
29
70
|
const ToggleGroupContext = React.createContext({
|
|
30
71
|
size: 'default',
|
|
31
72
|
variant: 'default',
|
|
32
|
-
spacing: 0
|
|
73
|
+
spacing: 0,
|
|
74
|
+
arrowKeyPressed: null
|
|
33
75
|
});
|
|
34
76
|
function ToggleGroup({ className, variant, size, spacing = 0, children, style, ...props }) {
|
|
77
|
+
// Read, never destructured: `type` is the discriminant of the Radix props
|
|
78
|
+
// union, and pulling it out then spreading it back widens the union so the
|
|
79
|
+
// single/multiple props stop resolving.
|
|
80
|
+
const arrowKeyPressed = useArrowKeyPressed(props.type === 'single');
|
|
35
81
|
return (_jsx(ToggleGroupPrimitive.Root, { "data-slot": "toggle-group", "data-variant": variant, "data-size": size, "data-spacing": spacing,
|
|
36
82
|
// Caller style first: `--gap` is ours and must survive, but everything
|
|
37
83
|
// else the caller passes has to reach the element.
|
|
@@ -39,13 +85,36 @@ function ToggleGroup({ className, variant, size, spacing = 0, children, style, .
|
|
|
39
85
|
// Legacy carried a `data-[spacing=default]:...:shadow-xs` rule here that
|
|
40
86
|
// never matched — `data-spacing` is always a number. Removed rather than
|
|
41
87
|
// activated, so the rendered pixels stay identical to sindarian-x.
|
|
42
|
-
'group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md', className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: { variant, size, spacing }, children: children }) }));
|
|
88
|
+
'group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md', className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: { variant, size, spacing, arrowKeyPressed }, children: children }) }));
|
|
43
89
|
}
|
|
44
|
-
function ToggleGroupItem({ className, children, variant, size, ...props }) {
|
|
90
|
+
function ToggleGroupItem({ className, children, variant, size, onFocus, ...props }) {
|
|
45
91
|
const context = React.useContext(ToggleGroupContext);
|
|
92
|
+
/**
|
|
93
|
+
* Selection follows focus, which is what `role="radio"` promises.
|
|
94
|
+
*
|
|
95
|
+
* With `type="single"` Radix puts the group on the ARIA radio pattern: the
|
|
96
|
+
* root is a `radiogroup`, each item a `radio` with `aria-checked`. Under that
|
|
97
|
+
* pattern an arrow key both moves focus and checks the item it lands on.
|
|
98
|
+
* Radix only moves focus, so a screen-reader operator used to arrow across
|
|
99
|
+
* "radio, not checked, 2 of 3" with nothing ever selected.
|
|
100
|
+
*
|
|
101
|
+
* `type="multiple"` is a `toolbar` of `aria-pressed` buttons and keeps its
|
|
102
|
+
* current behavior, where moving focus without pressing is correct: the flag
|
|
103
|
+
* is null there.
|
|
104
|
+
*
|
|
105
|
+
* Clicking the element rather than writing the value keeps a single
|
|
106
|
+
* activation path, so Radix's own toggle and any caller `onClick` both fire
|
|
107
|
+
* exactly as they do for a real click.
|
|
108
|
+
*/
|
|
109
|
+
const handleFocus = (event) => {
|
|
110
|
+
onFocus?.(event);
|
|
111
|
+
if (context.arrowKeyPressed?.current) {
|
|
112
|
+
event.currentTarget.click();
|
|
113
|
+
}
|
|
114
|
+
};
|
|
46
115
|
return (_jsx(ToggleGroupPrimitive.Item, { "data-slot": "toggle-group-item", "data-variant": context.variant || variant, "data-size": context.size || size, "data-spacing": context.spacing, className: cn(toggleVariants({
|
|
47
116
|
variant: context.variant || variant,
|
|
48
117
|
size: context.size || size
|
|
49
|
-
}), 'w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10', 'data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l', className), ...props, children: children }));
|
|
118
|
+
}), 'w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10', 'data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l', className), ...props, onFocus: handleFocus, children: children }));
|
|
50
119
|
}
|
|
51
120
|
export { ToggleGroup, ToggleGroupItem };
|
|
@@ -6,6 +6,21 @@ export type TooltipProps = React.ComponentProps<typeof TooltipPrimitive.Root> &
|
|
|
6
6
|
};
|
|
7
7
|
declare function Tooltip({ open: _open, onOpenChange, disabled, ...props }: TooltipProps): React.JSX.Element;
|
|
8
8
|
declare function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>): React.JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* The fill is a RAW palette step, not a theme token: `--color-shadcn-600` is a
|
|
11
|
+
* flat hex, so an inverted tooltip stays #27272A under both themes. The ink has
|
|
12
|
+
* to be theme-fixed too, which rules out `--primary-foreground` and
|
|
13
|
+
* `--background`: both invert, and both land on 1.00:1 against this fill in
|
|
14
|
+
* dark.
|
|
15
|
+
*
|
|
16
|
+
* base/400 was not unreadable here (5.81:1 on this fill; the 2.56:1 figure that
|
|
17
|
+
* class earns elsewhere is against a LIGHT ground, which this is not). It moved
|
|
18
|
+
* one step to base/300 because base/400 is banned kit-wide in
|
|
19
|
+
* `__tests__/ink-classes.test.ts`: its only safe ground is a fixed-dark fill,
|
|
20
|
+
* and that narrow exception had already leaked into eight slots that were not
|
|
21
|
+
* one. base/300 reads 10.08:1 here, and keeps this line quieter than the
|
|
22
|
+
* `text-white` a consumer puts beside it (`page-header/index.tsx:226`).
|
|
23
|
+
*/
|
|
9
24
|
declare function TooltipContent({ className, sideOffset, children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Content>): React.JSX.Element;
|
|
10
25
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
11
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/tooltip/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAI3D,iBAAS,eAAe,CAAC,EACvB,aAAiB,EACjB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,qBAQxD;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAC7C,OAAO,gBAAgB,CAAC,IAAI,CAC7B,GAAG;IACF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,iBAAS,OAAO,CAAC,EACf,IAAI,EAAE,KAAK,EACX,YAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,YAAY,qBAwBd;AAED,iBAAS,cAAc,CAAC,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,qBAEvD;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,UAAc,EACd,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,qBAiBvD;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/tooltip/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAI3D,iBAAS,eAAe,CAAC,EACvB,aAAiB,EACjB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,qBAQxD;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAC7C,OAAO,gBAAgB,CAAC,IAAI,CAC7B,GAAG;IACF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,iBAAS,OAAO,CAAC,EACf,IAAI,EAAE,KAAK,EACX,YAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,YAAY,qBAwBd;AAED,iBAAS,cAAc,CAAC,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,qBAEvD;AAED;;;;;;;;;;;;;;GAcG;AACH,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,UAAc,EACd,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,qBAiBvD;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -22,7 +22,22 @@ function Tooltip({ open: _open, onOpenChange, disabled, ...props }) {
|
|
|
22
22
|
function TooltipTrigger({ ...props }) {
|
|
23
23
|
return _jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* The fill is a RAW palette step, not a theme token: `--color-shadcn-600` is a
|
|
27
|
+
* flat hex, so an inverted tooltip stays #27272A under both themes. The ink has
|
|
28
|
+
* to be theme-fixed too, which rules out `--primary-foreground` and
|
|
29
|
+
* `--background`: both invert, and both land on 1.00:1 against this fill in
|
|
30
|
+
* dark.
|
|
31
|
+
*
|
|
32
|
+
* base/400 was not unreadable here (5.81:1 on this fill; the 2.56:1 figure that
|
|
33
|
+
* class earns elsewhere is against a LIGHT ground, which this is not). It moved
|
|
34
|
+
* one step to base/300 because base/400 is banned kit-wide in
|
|
35
|
+
* `__tests__/ink-classes.test.ts`: its only safe ground is a fixed-dark fill,
|
|
36
|
+
* and that narrow exception had already leaked into eight slots that were not
|
|
37
|
+
* one. base/300 reads 10.08:1 here, and keeps this line quieter than the
|
|
38
|
+
* `text-white` a consumer puts beside it (`page-header/index.tsx:226`).
|
|
39
|
+
*/
|
|
25
40
|
function TooltipContent({ className, sideOffset = 0, children, ...props }) {
|
|
26
|
-
return (_jsx(TooltipPrimitive.Portal, { children: _jsxs(TooltipPrimitive.Content, { "data-slot": "tooltip-content", sideOffset: sideOffset, className: cn('bg-shadcn-600 text-shadcn-
|
|
41
|
+
return (_jsx(TooltipPrimitive.Portal, { children: _jsxs(TooltipPrimitive.Content, { "data-slot": "tooltip-content", sideOffset: sideOffset, className: cn('bg-shadcn-600 text-shadcn-300 motion-safe:animate-in fade-in-0 zoom-in-95 motion-safe:data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 rounded-md px-3 py-1.5 text-sm shadow-md', className), ...props, children: [children, _jsx(TooltipPrimitive.Arrow, { className: "bg-shadcn-600 fill-shadcn-600 z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })] }) }));
|
|
27
42
|
}
|
|
28
43
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
* — no zebra fills. Each row: a quiet sentence-case sans label on the left, a mono
|
|
6
6
|
* `tabular-nums` value on the right, `hover:bg-body-surface` as the quiet row
|
|
7
7
|
* affordance (the recessed page surface, one step behind `bg-card`, in both
|
|
8
|
-
* themes). Escalate the value color (`text-credit`, `text-system-alert`)
|
|
9
|
-
* when a metric crosses a threshold
|
|
8
|
+
* themes). Escalate the value color (`text-credit`, `text-system-alert-h1a`)
|
|
9
|
+
* only when a metric crosses a threshold — the INK tokens, never the bare
|
|
10
|
+
* `text-system-*` fills, which are picked to carry white and read as low as
|
|
11
|
+
* 1.78:1 on this surface in light.
|
|
10
12
|
*
|
|
11
13
|
* <Blotter>
|
|
12
14
|
* <BlotterRow label="Resolved on time" value="128" />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/blotter/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/blotter/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtC,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,YAAY,+BAE5D;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,SAAS,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;IAChB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,cAAc,EACd,SAAS,EACT,OAAe,EACf,OAAe,EAChB,EAAE,eAAe,+BAkDjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aging-buckets.d.ts","sourceRoot":"","sources":["../../../../src/domain/delinquency-aging/aging-buckets.tsx"],"names":[],"mappings":"AAyCA,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAElE;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC1C,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yEAAyE;IACzE,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B;oFACgF;IAChF,WAAW,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"aging-buckets.d.ts","sourceRoot":"","sources":["../../../../src/domain/delinquency-aging/aging-buckets.tsx"],"names":[],"mappings":"AAyCA,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAElE;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC1C,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yEAAyE;IACzE,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B;oFACgF;IAChF,WAAW,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAgCD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EAAE,EACtB,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAMf;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAiB,EACjB,MAAM,EACN,WAAuB,EACvB,SAAS,EACV,EAAE,iBAAiB,+BAkHnB"}
|
|
@@ -38,11 +38,16 @@ import { minorDigitsOf, minorToDecimal, sumMinor } from '../money-math.js';
|
|
|
38
38
|
import { MoneyText } from '../money-text/index.js';
|
|
39
39
|
/** Band → glyph + tint + accessible word. The glyph (and the sr-only word) is
|
|
40
40
|
* the load-bearing severity cue; the tint only reinforces it, so the
|
|
41
|
-
* escalation survives grayscale and color-vision deficiency.
|
|
41
|
+
* escalation survives grayscale and color-vision deficiency.
|
|
42
|
+
*
|
|
43
|
+
* The tint is an INK token (`-h1a`). A load-bearing glyph answers to the 3:1
|
|
44
|
+
* floor of SC 1.4.11, and the bare fill token `--system-alert` reads 1.78:1 on
|
|
45
|
+
* `--card` and 1.62:1 on `--body-surface` in light — the cue was invisible on
|
|
46
|
+
* the row it escalates. */
|
|
42
47
|
const BAND = {
|
|
43
48
|
current: {
|
|
44
49
|
Icon: CircleDot,
|
|
45
|
-
tint: 'text-system-success',
|
|
50
|
+
tint: 'text-system-success-h1a',
|
|
46
51
|
word: 'Em dia'
|
|
47
52
|
},
|
|
48
53
|
recent: {
|
|
@@ -52,7 +57,7 @@ const BAND = {
|
|
|
52
57
|
},
|
|
53
58
|
aging: {
|
|
54
59
|
Icon: AlertTriangle,
|
|
55
|
-
tint: 'text-system-alert',
|
|
60
|
+
tint: 'text-system-alert-h1a',
|
|
56
61
|
word: 'Em atraso'
|
|
57
62
|
},
|
|
58
63
|
overdue: { Icon: AlertOctagon, tint: 'text-credit', word: 'Vencido' }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/delinquency-aging/index.tsx"],"names":[],"mappings":"AAoDA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAKtE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAOpE;;wEAEwE;AACxE,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;oEACoE;AACpE,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iFAAiF;IACjF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;0EAEsE;IACtE,aAAa,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,KAAK,EAAE,MAAM,GACZ,eAAe,CAuDjB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/delinquency-aging/index.tsx"],"names":[],"mappings":"AAoDA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAKtE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAOpE;;wEAEwE;AACxE,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;oEACoE;AACpE,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iFAAiF;IACjF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;0EAEsE;IACtE,aAAa,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,KAAK,EAAE,MAAM,GACZ,eAAe,CAuDjB;AAyFD,MAAM,WAAW,qBAAqB;IACpC;yEACqE;IACrE,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;sBAGkB;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IACnD,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;oBAEgB;IAChB,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC;;;mDAG+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;yEACqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAA2B,EAC3B,cAAc,EACd,UAA2B,EAC3B,kBAAoC,EACpC,YAAY,EACZ,IAAW,EACX,MAAY,EACZ,SAAiB,EACjB,WAAuB,EACvB,SAAS,EACV,EAAE,qBAAqB,+BA6EvB"}
|
|
@@ -178,10 +178,15 @@ function exactBand(overdue, total, warn, breach) {
|
|
|
178
178
|
/** Band → glyph + tint + accessible word. The glyph and sr-only word are the
|
|
179
179
|
* load-bearing cue; the tint only reinforces, so the band survives grayscale
|
|
180
180
|
* and color-vision deficiency. Mirrors the gauge's three-band canon, renamed
|
|
181
|
-
* to the delinquency vocabulary.
|
|
181
|
+
* to the delinquency vocabulary.
|
|
182
|
+
*
|
|
183
|
+
* The tint is an INK token (`-h1a`), because it is painted on the `Figure`
|
|
184
|
+
* below as well as on the glyph. The bare fill tokens read 1.78:1
|
|
185
|
+
* (`--system-alert`) and 3.35:1 (`--system-success`) on every light surface in
|
|
186
|
+
* the kit — the alert one under even the 3:1 floor a glyph answers to. */
|
|
182
187
|
const RATE_BAND = {
|
|
183
|
-
low: { Icon: ShieldCheck, tint: 'text-system-success', word: 'Saudável' },
|
|
184
|
-
warn: { Icon: TriangleAlert, tint: 'text-system-alert', word: 'Elevada' },
|
|
188
|
+
low: { Icon: ShieldCheck, tint: 'text-system-success-h1a', word: 'Saudável' },
|
|
189
|
+
warn: { Icon: TriangleAlert, tint: 'text-system-alert-h1a', word: 'Elevada' },
|
|
185
190
|
breach: { Icon: AlertOctagon, tint: 'text-credit', word: 'Em estresse' }
|
|
186
191
|
};
|
|
187
192
|
export function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadimplência', rateBandLabels, emptyLabel = 'sem carteira', indeterminateLabel = 'indeterminada', bucketLabels, warn = 0.05, breach = 0.1, showTotal = false, healthyTone = 'success', className }) {
|
|
@@ -165,5 +165,5 @@ function CopyValue({ value }) {
|
|
|
165
165
|
setCopied(false);
|
|
166
166
|
});
|
|
167
167
|
};
|
|
168
|
-
return (_jsx("button", { type: "button", onClick: copy, "aria-label": copied ? 'Copiado para a área de transferência' : 'Copiar valor', className: "text-muted-foreground hover:text-foreground focus:ring-ring inline-flex size-5 shrink-0 items-center justify-center rounded-sm transition-colors duration-150 ease-out focus:ring-2 focus:outline-none", children: copied ? (_jsx(Check, { "aria-hidden": true, className: "text-system-success size-3" })) : (_jsx(Copy, { "aria-hidden": true, className: "size-3" })) }));
|
|
168
|
+
return (_jsx("button", { type: "button", onClick: copy, "aria-label": copied ? 'Copiado para a área de transferência' : 'Copiar valor', className: "text-muted-foreground hover:text-foreground focus:ring-ring inline-flex size-5 shrink-0 items-center justify-center rounded-sm transition-colors duration-150 ease-out focus:ring-2 focus:outline-none", children: copied ? (_jsx(Check, { "aria-hidden": true, className: "text-system-success-h1a size-3" })) : (_jsx(Copy, { "aria-hidden": true, className: "size-3" })) }));
|
|
169
169
|
}
|
|
@@ -45,7 +45,7 @@ export function StatusRail({ lead, items = [], chips = [], className }) {
|
|
|
45
45
|
// Tiny mono token: raised a hair off the sunken tape by the
|
|
46
46
|
// card surface + whisper shadow.
|
|
47
47
|
'inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 shadow-sm', chip.alarm
|
|
48
|
-
? 'border-destructive/40 bg-destructive/10 text-
|
|
48
|
+
? 'border-destructive/40 bg-destructive/10 text-system-error-h1a'
|
|
49
49
|
: 'border-border bg-card text-foreground'), children: [chip.alarm ? (_jsxs(_Fragment, { children: [_jsx(TriangleAlert, { "aria-hidden": true, className: "size-3" }), _jsx("span", { className: "sr-only", children: "(alarme)" })] })) : null, chip.value] })] }, chip.id ?? i))) })) : null] }));
|
|
50
50
|
}
|
|
51
51
|
/** A tape item preceded by a separator dot when it is not the first token. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/threshold-gauge/index.tsx"],"names":[],"mappings":"AAiDA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEjD;gFACgF;AAChF,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAEjE;;gDAEgD;AAChD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAEjE;;;;wEAIwE;AACxE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAA;AAE/C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;oEACgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb;;;;iDAI6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,qEAAqE;IACrE,SAAS,EAAE,cAAc,CAAA;IACzB,qDAAqD;IACrD,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;uCAImC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;0EAIsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/threshold-gauge/index.tsx"],"names":[],"mappings":"AAiDA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEjD;gFACgF;AAChF,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAEjE;;gDAEgD;AAChD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAEjE;;;;wEAIwE;AACxE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAA;AAE/C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;oEACgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb;;;;iDAI6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,qEAAqE;IACrE,SAAS,EAAE,cAAc,CAAA;IACzB,qDAAqD;IACrD,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;uCAImC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;0EAIsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAuCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,cAAc,GACxB,SAAS,CAUX;AA+CD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,YAAY,EACZ,GAAO,EACP,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,MAAkB,EAClB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACV,EAAE,mBAAmB,+BA8ErB"}
|
|
@@ -51,22 +51,26 @@ import { MoneyText } from '../money-text/index.js';
|
|
|
51
51
|
const BAND = {
|
|
52
52
|
low: {
|
|
53
53
|
Icon: ShieldCheck,
|
|
54
|
-
tint: 'text-system-success',
|
|
54
|
+
tint: 'text-system-success-h1a',
|
|
55
55
|
word: 'Dentro do limite'
|
|
56
56
|
},
|
|
57
57
|
warn: {
|
|
58
58
|
Icon: TriangleAlert,
|
|
59
|
-
tint: 'text-system-alert',
|
|
59
|
+
tint: 'text-system-alert-h1a',
|
|
60
60
|
word: 'Próximo do limite'
|
|
61
61
|
},
|
|
62
62
|
breach: {
|
|
63
63
|
Icon: OctagonX,
|
|
64
|
-
tint: 'text-
|
|
64
|
+
tint: 'text-system-error-h1a',
|
|
65
65
|
word: 'Limite ultrapassado'
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
|
-
/** Track fill tint per band
|
|
69
|
-
*
|
|
68
|
+
/** Track fill tint per band, and the reason it is a SEPARATE map from the
|
|
69
|
+
* tint above: these are the fill tokens, and a fill answers to no text floor.
|
|
70
|
+
* The tint above is painted on the band glyph AND on the `Figure`, so it has
|
|
71
|
+
* to be the ink family. Light `--system-alert` is #EAB308, about 1.9:1 on
|
|
72
|
+
* white, and `--system-success` about 3.3:1 — both were readable only as a
|
|
73
|
+
* bar wash, never as the number the reader is here to read. */
|
|
70
74
|
const BAND_FILL = {
|
|
71
75
|
low: 'bg-system-success',
|
|
72
76
|
warn: 'bg-system-alert',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/stat-card/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAQtC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/stat-card/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAQtC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAA;AA4B5E,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,SAAS,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAA;IACb,iEAAiE;IACjE,KAAK,EAAE,SAAS,CAAA;IAChB,4FAA4F;IAC5F,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,uDAAuD;IACvD,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,sDAAsD;IACtD,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;IAC7D,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAwED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,KAAK,EACL,KAAK,EACL,IAAgB,EAChB,KAAK,EACL,QAAkB,EAClB,IAAI,EACJ,SAAS,EACV,EAAE,aAAa,+BAgCf"}
|
|
@@ -5,12 +5,20 @@ import { LedgerPanel } from '../../domain/ledger-sheet/index.js';
|
|
|
5
5
|
import { SectionLabel } from '../../domain/section-label/index.js';
|
|
6
6
|
import { cn } from '../../lib/utils.js';
|
|
7
7
|
/** Value/delta color per tone. `default` keeps the high-contrast foreground;
|
|
8
|
-
* the rest escalate to a semantic theme token that tracks light/dark.
|
|
8
|
+
* the rest escalate to a semantic theme token that tracks light/dark.
|
|
9
|
+
*
|
|
10
|
+
* All three escalations read the `-h1a` family, not a mix of `-h1a` and
|
|
11
|
+
* `-text`. `--system-*-text` is the ink of a tinted PILL, measured against its
|
|
12
|
+
* own surface; this card paints on the panel, and `-h1a` is the family gated
|
|
13
|
+
* against `--card` and `--background` in `__tests__/tokens-contract.test.ts`.
|
|
14
|
+
* The two differ by one palette step in dark, so a mixed table gave the three
|
|
15
|
+
* deltas three different weights on the same surface for no reason a reader
|
|
16
|
+
* could see. */
|
|
9
17
|
const TONE_VALUE = {
|
|
10
18
|
default: 'text-foreground',
|
|
11
|
-
success: 'text-system-success-
|
|
12
|
-
warning: 'text-system-alert-
|
|
13
|
-
destructive: 'text-
|
|
19
|
+
success: 'text-system-success-h1a',
|
|
20
|
+
warning: 'text-system-alert-h1a',
|
|
21
|
+
destructive: 'text-system-error-h1a'
|
|
14
22
|
};
|
|
15
23
|
/** Trend stroke color per tone. Resolved through the `--color-*` wrappers (the
|
|
16
24
|
* raw `--chart-N` tokens are bare HSL triples, not usable colors). */
|