@acronis-platform/ui-react 0.57.1 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ui/area-chart/area-chart.js +149 -0
- package/dist/components/ui/area-chart/area-chart.js.map +1 -0
- package/dist/components/ui/bar-chart/bar-chart.js +152 -77
- package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
- package/dist/components/ui/button-icon-input/button-icon-input.js +36 -0
- package/dist/components/ui/button-icon-input/button-icon-input.js.map +1 -0
- package/dist/components/ui/button-menu/button-menu.js +1 -1
- package/dist/components/ui/button-menu/button-menu.js.map +1 -1
- package/dist/components/ui/card-filter/card-filter.js +40 -27
- package/dist/components/ui/card-filter/card-filter.js.map +1 -1
- package/dist/components/ui/chart-state/chart-state.js +42 -0
- package/dist/components/ui/chart-state/chart-state.js.map +1 -0
- package/dist/components/ui/chip/chip.js +13 -13
- package/dist/components/ui/chip/chip.js.map +1 -1
- package/dist/components/ui/composed-chart/composed-chart.js +107 -0
- package/dist/components/ui/composed-chart/composed-chart.js.map +1 -0
- package/dist/components/ui/confidence-cone/confidence-cone.js +195 -0
- package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -0
- package/dist/components/ui/date-range-picker/date-range-picker.js +21 -21
- package/dist/components/ui/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/ui/dialog/dialog.js +250 -78
- package/dist/components/ui/dialog/dialog.js.map +1 -1
- package/dist/components/ui/dialog-footer-default/dialog-footer-default.js +26 -0
- package/dist/components/ui/dialog-footer-default/dialog-footer-default.js.map +1 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.js +21 -21
- package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/ui/filter-search/filter-search.js +91 -90
- package/dist/components/ui/filter-search/filter-search.js.map +1 -1
- package/dist/components/ui/funnel-chart/funnel-chart.js +87 -0
- package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -0
- package/dist/components/ui/histogram/histogram.js +108 -0
- package/dist/components/ui/histogram/histogram.js.map +1 -0
- package/dist/components/ui/input-otp/input-otp.js +104 -0
- package/dist/components/ui/input-otp/input-otp.js.map +1 -0
- package/dist/components/ui/input-password/input-password.js +120 -0
- package/dist/components/ui/input-password/input-password.js.map +1 -0
- package/dist/components/ui/input-text/input-text.js +9 -9
- package/dist/components/ui/input-text/input-text.js.map +1 -1
- package/dist/components/ui/line-chart/line-chart.js +206 -0
- package/dist/components/ui/line-chart/line-chart.js.map +1 -0
- package/dist/components/ui/link/link.js +5 -5
- package/dist/components/ui/link/link.js.map +1 -1
- package/dist/components/ui/loading/loading.js +79 -0
- package/dist/components/ui/loading/loading.js.map +1 -0
- package/dist/components/ui/meter/meter.js +93 -0
- package/dist/components/ui/meter/meter.js.map +1 -0
- package/dist/components/ui/metric/metric.js +185 -0
- package/dist/components/ui/metric/metric.js.map +1 -0
- package/dist/components/ui/pie-chart/pie-chart.js +113 -0
- package/dist/components/ui/pie-chart/pie-chart.js.map +1 -0
- package/dist/components/ui/popover/popover.js +57 -27
- package/dist/components/ui/popover/popover.js.map +1 -1
- package/dist/components/ui/radar-chart/radar-chart.js +74 -0
- package/dist/components/ui/radar-chart/radar-chart.js.map +1 -0
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +69 -0
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -0
- package/dist/components/ui/scatter-chart/scatter-chart.js +102 -0
- package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -0
- package/dist/components/ui/search/search.js +16 -16
- package/dist/components/ui/search/search.js.map +1 -1
- package/dist/components/ui/sheet/sheet-details.js +16 -16
- package/dist/components/ui/sheet/sheet-details.js.map +1 -1
- package/dist/components/ui/spinner/spinner.js.map +1 -1
- package/dist/components/ui/timeline/timeline.js +175 -0
- package/dist/components/ui/timeline/timeline.js.map +1 -0
- package/dist/components/ui/treemap/treemap.js +83 -0
- package/dist/components/ui/treemap/treemap.js.map +1 -0
- package/dist/components/ui/trend-indicator/trend-indicator.js +97 -0
- package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -0
- package/dist/index.js +423 -384
- package/dist/index.js.map +1 -1
- package/dist/react.js +423 -384
- package/dist/react.js.map +1 -1
- package/dist/src/components/ui/area-chart/area-chart.d.ts +49 -0
- package/dist/src/components/ui/area-chart/index.d.ts +1 -0
- package/dist/src/components/ui/avatar/avatar.d.ts +1 -1
- package/dist/src/components/ui/bar-chart/bar-chart.d.ts +42 -2
- package/dist/src/components/ui/bar-chart/index.d.ts +1 -1
- package/dist/src/components/ui/button-icon-input/button-icon-input.d.ts +21 -0
- package/dist/src/components/ui/button-icon-input/index.d.ts +1 -0
- package/dist/src/components/ui/card-filter/card-filter.d.ts +5 -0
- package/dist/src/components/ui/chart-state/chart-state.d.ts +11 -0
- package/dist/src/components/ui/chart-state/index.d.ts +1 -0
- package/dist/src/components/ui/composed-chart/composed-chart.d.ts +48 -0
- package/dist/src/components/ui/composed-chart/index.d.ts +1 -0
- package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +79 -0
- package/dist/src/components/ui/confidence-cone/index.d.ts +1 -0
- package/dist/src/components/ui/dialog/dialog.d.ts +105 -9
- package/dist/src/components/ui/dialog/dialog.docs.d.ts +82 -5
- package/dist/src/components/ui/dialog/index.d.ts +1 -1
- package/dist/src/components/ui/dialog-footer-default/dialog-footer-default.d.ts +11 -0
- package/dist/src/components/ui/dialog-footer-default/index.d.ts +1 -0
- package/dist/src/components/ui/filter-search/filter-search.d.ts +1 -1
- package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +39 -0
- package/dist/src/components/ui/funnel-chart/index.d.ts +1 -0
- package/dist/src/components/ui/histogram/histogram.d.ts +55 -0
- package/dist/src/components/ui/histogram/index.d.ts +1 -0
- package/dist/src/components/ui/input-otp/index.d.ts +1 -0
- package/dist/src/components/ui/input-otp/input-otp.d.ts +23 -0
- package/dist/src/components/ui/input-password/index.d.ts +1 -0
- package/dist/src/components/ui/input-password/input-password.d.ts +21 -0
- package/dist/src/components/ui/line-chart/index.d.ts +1 -0
- package/dist/src/components/ui/line-chart/line-chart.d.ts +83 -0
- package/dist/src/components/ui/loading/index.d.ts +1 -0
- package/dist/src/components/ui/loading/loading.d.ts +13 -0
- package/dist/src/components/ui/meter/index.d.ts +1 -0
- package/dist/src/components/ui/meter/meter.d.ts +25 -0
- package/dist/src/components/ui/metric/index.d.ts +1 -0
- package/dist/src/components/ui/metric/metric.d.ts +37 -0
- package/dist/src/components/ui/pie-chart/index.d.ts +1 -0
- package/dist/src/components/ui/pie-chart/pie-chart.d.ts +54 -0
- package/dist/src/components/ui/popover/index.d.ts +1 -1
- package/dist/src/components/ui/popover/popover.d.ts +13 -1
- package/dist/src/components/ui/radar-chart/index.d.ts +1 -0
- package/dist/src/components/ui/radar-chart/radar-chart.d.ts +40 -0
- package/dist/src/components/ui/radial-bar-chart/index.d.ts +1 -0
- package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +45 -0
- package/dist/src/components/ui/scatter-chart/index.d.ts +1 -0
- package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +50 -0
- package/dist/src/components/ui/stack/stack.d.ts +1 -1
- package/dist/src/components/ui/timeline/index.d.ts +1 -0
- package/dist/src/components/ui/timeline/timeline.d.ts +41 -0
- package/dist/src/components/ui/treemap/index.d.ts +1 -0
- package/dist/src/components/ui/treemap/treemap.d.ts +44 -0
- package/dist/src/components/ui/trend-indicator/index.d.ts +1 -0
- package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +32 -0
- package/dist/src/index.d.ts +22 -2
- package/dist/ui-react.css +1 -1
- package/package.json +3 -3
|
@@ -10,19 +10,19 @@ const T = m.forwardRef(
|
|
|
10
10
|
label: i,
|
|
11
11
|
required: u,
|
|
12
12
|
description: v,
|
|
13
|
-
error:
|
|
13
|
+
error: o,
|
|
14
14
|
clearable: f,
|
|
15
15
|
onClear: h,
|
|
16
16
|
disabled: e,
|
|
17
|
-
value:
|
|
17
|
+
value: a,
|
|
18
18
|
...I
|
|
19
19
|
}, N) => {
|
|
20
|
-
const y = m.useId(),
|
|
20
|
+
const y = m.useId(), r = b ?? y, d = `${r}-message`, l = o != null && o !== "", w = a != null && a !== "", p = !!f && w && !e, n = l ? o : v, x = n != null && n !== "";
|
|
21
21
|
return /* @__PURE__ */ s("div", { className: "flex w-full min-w-[var(--ui-input-text-global-container-width-min)] flex-col gap-[var(--ui-input-text-global-container-gap)]", children: [
|
|
22
22
|
i != null && i !== "" && /* @__PURE__ */ s(
|
|
23
23
|
"label",
|
|
24
24
|
{
|
|
25
|
-
htmlFor:
|
|
25
|
+
htmlFor: r,
|
|
26
26
|
className: c(
|
|
27
27
|
"flex gap-[var(--ui-input-text-global-container-label-gap)] text-sm leading-4",
|
|
28
28
|
e ? "text-[var(--ui-input-text-global-label-color-disabled)]" : "text-[var(--ui-input-text-global-label-color-idle)]"
|
|
@@ -45,10 +45,10 @@ const T = m.forwardRef(
|
|
|
45
45
|
C,
|
|
46
46
|
{
|
|
47
47
|
ref: N,
|
|
48
|
-
id:
|
|
48
|
+
id: r,
|
|
49
49
|
disabled: e,
|
|
50
|
-
value:
|
|
51
|
-
"aria-invalid":
|
|
50
|
+
value: a,
|
|
51
|
+
"aria-invalid": l || void 0,
|
|
52
52
|
"aria-required": u || void 0,
|
|
53
53
|
"aria-describedby": x ? d : void 0,
|
|
54
54
|
className: c(p && "pe-9", g),
|
|
@@ -61,7 +61,7 @@ const T = m.forwardRef(
|
|
|
61
61
|
type: "button",
|
|
62
62
|
onClick: h,
|
|
63
63
|
"aria-label": "Clear",
|
|
64
|
-
className: "absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-
|
|
64
|
+
className: "absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-5 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[var(--ui-input-text-global-box-border-radius)] p-0.5 text-[var(--ui-button-icon-global-icon-color-idle)] outline-none hover:bg-[var(--ui-button-icon-global-container-color-hover)] active:bg-[var(--ui-button-icon-global-container-color-active)] focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] [&_svg]:size-4 [&_svg]:shrink-0",
|
|
65
65
|
children: /* @__PURE__ */ t(j, {})
|
|
66
66
|
}
|
|
67
67
|
)
|
|
@@ -72,7 +72,7 @@ const T = m.forwardRef(
|
|
|
72
72
|
id: d,
|
|
73
73
|
className: c(
|
|
74
74
|
"text-xs leading-4",
|
|
75
|
-
|
|
75
|
+
l ? "text-[var(--ui-input-text-error-msg-error-color)]" : e ? "text-[var(--ui-input-text-normal-description-color-disabled)]" : "text-[var(--ui-input-text-normal-description-color-idle)]"
|
|
76
76
|
),
|
|
77
77
|
children: n
|
|
78
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-text.js","sources":["../../../../src/components/ui/input-text/input-text.tsx"],"sourcesContent":["import * as React from 'react';\nimport { TimesIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { InputBox } from '../input';\n\n// Mirrors the Figma \"InputText\" component: a full single-line text field built\n// around the bare `InputBox` primitive (themed by the `--ui-input-text-*` tier). It\n// adds the field furniture: an optional `label` (with an optional `required` `*`),\n// an optional clear (✕) button, and an optional `description` or `error` message\n// below. Passing `error` switches the field to its error treatment — the box gets\n// the red error border (via the input's `aria-invalid` styling) and the red error\n// message replaces the description. The clear button appears only while `clearable`\n// is set and the (controlled) field has a value, and calls `onClear`. Colors come\n// from the `--ui-input-text-*` tokens — label/required/description/error — so brand\n// overrides are honored; the clear button is a ghost ButtonIcon (glyph\n// `--ui-button-icon-global-icon-color-idle`, since the input-text tier dropped its\n// own clear-icon token in the Figma sync) with a 3px `--ui-focus-primary` ring.\nexport interface InputTextProps\n extends Omit<React.ComponentPropsWithoutRef<'input'>, 'children'> {\n /** Field label, rendered above the input. */\n label?: React.ReactNode;\n /** Marks the field required — appends a `*` after the label. */\n required?: boolean;\n /** Helper text below the input. Hidden while `error` is set. */\n description?: React.ReactNode;\n /**\n * Error message below the input. Its presence switches the field to the error\n * treatment (red box border + red message).\n */\n error?: React.ReactNode;\n /** Show a clear (✕) button while the (controlled) field has a value. */\n clearable?: boolean;\n /** Called when the clear button is activated. */\n onClear?: () => void;\n}\n\nconst InputText = React.forwardRef<HTMLInputElement, InputTextProps>(\n (\n {\n className,\n id,\n label,\n required,\n description,\n error,\n clearable,\n onClear,\n disabled,\n value,\n ...props\n },\n ref\n ) => {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n const messageId = `${inputId}-message`;\n\n const hasError = error != null && error !== '';\n const hasValue = value != null && value !== '';\n const showClear = Boolean(clearable) && hasValue && !disabled;\n const message = hasError ? error : description;\n const hasMessage = message != null && message !== '';\n\n return (\n <div className=\"flex w-full min-w-[var(--ui-input-text-global-container-width-min)] flex-col gap-[var(--ui-input-text-global-container-gap)]\">\n {label != null && label !== '' && (\n <label\n htmlFor={inputId}\n className={cn(\n 'flex gap-[var(--ui-input-text-global-container-label-gap)] text-sm leading-4',\n disabled\n ? 'text-[var(--ui-input-text-global-label-color-disabled)]'\n : 'text-[var(--ui-input-text-global-label-color-idle)]'\n )}\n >\n {label}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-text-global-required-color)]\"\n >\n *\n </span>\n )}\n </label>\n )}\n\n <div className=\"relative\">\n <InputBox\n ref={ref}\n id={inputId}\n disabled={disabled}\n value={value}\n aria-invalid={hasError || undefined}\n aria-required={required || undefined}\n aria-describedby={hasMessage ? messageId : undefined}\n className={cn(showClear && 'pe-9', className)}\n {...props}\n />\n {showClear && (\n <button\n type=\"button\"\n onClick={onClear}\n aria-label=\"Clear\"\n className=\"absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-
|
|
1
|
+
{"version":3,"file":"input-text.js","sources":["../../../../src/components/ui/input-text/input-text.tsx"],"sourcesContent":["import * as React from 'react';\nimport { TimesIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { InputBox } from '../input';\n\n// Mirrors the Figma \"InputText\" component: a full single-line text field built\n// around the bare `InputBox` primitive (themed by the `--ui-input-text-*` tier). It\n// adds the field furniture: an optional `label` (with an optional `required` `*`),\n// an optional clear (✕) button, and an optional `description` or `error` message\n// below. Passing `error` switches the field to its error treatment — the box gets\n// the red error border (via the input's `aria-invalid` styling) and the red error\n// message replaces the description. The clear button appears only while `clearable`\n// is set and the (controlled) field has a value, and calls `onClear`. Colors come\n// from the `--ui-input-text-*` tokens — label/required/description/error — so brand\n// overrides are honored; the clear button is a ghost ButtonIcon (glyph\n// `--ui-button-icon-global-icon-color-idle`, since the input-text tier dropped its\n// own clear-icon token in the Figma sync) with a 3px `--ui-focus-primary` ring.\nexport interface InputTextProps\n extends Omit<React.ComponentPropsWithoutRef<'input'>, 'children'> {\n /** Field label, rendered above the input. */\n label?: React.ReactNode;\n /** Marks the field required — appends a `*` after the label. */\n required?: boolean;\n /** Helper text below the input. Hidden while `error` is set. */\n description?: React.ReactNode;\n /**\n * Error message below the input. Its presence switches the field to the error\n * treatment (red box border + red message).\n */\n error?: React.ReactNode;\n /** Show a clear (✕) button while the (controlled) field has a value. */\n clearable?: boolean;\n /** Called when the clear button is activated. */\n onClear?: () => void;\n}\n\nconst InputText = React.forwardRef<HTMLInputElement, InputTextProps>(\n (\n {\n className,\n id,\n label,\n required,\n description,\n error,\n clearable,\n onClear,\n disabled,\n value,\n ...props\n },\n ref\n ) => {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n const messageId = `${inputId}-message`;\n\n const hasError = error != null && error !== '';\n const hasValue = value != null && value !== '';\n const showClear = Boolean(clearable) && hasValue && !disabled;\n const message = hasError ? error : description;\n const hasMessage = message != null && message !== '';\n\n return (\n <div className=\"flex w-full min-w-[var(--ui-input-text-global-container-width-min)] flex-col gap-[var(--ui-input-text-global-container-gap)]\">\n {label != null && label !== '' && (\n <label\n htmlFor={inputId}\n className={cn(\n 'flex gap-[var(--ui-input-text-global-container-label-gap)] text-sm leading-4',\n disabled\n ? 'text-[var(--ui-input-text-global-label-color-disabled)]'\n : 'text-[var(--ui-input-text-global-label-color-idle)]'\n )}\n >\n {label}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-text-global-required-color)]\"\n >\n *\n </span>\n )}\n </label>\n )}\n\n <div className=\"relative\">\n <InputBox\n ref={ref}\n id={inputId}\n disabled={disabled}\n value={value}\n aria-invalid={hasError || undefined}\n aria-required={required || undefined}\n aria-describedby={hasMessage ? messageId : undefined}\n className={cn(showClear && 'pe-9', className)}\n {...props}\n />\n {showClear && (\n <button\n type=\"button\"\n onClick={onClear}\n aria-label=\"Clear\"\n className=\"absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-5 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[var(--ui-input-text-global-box-border-radius)] p-0.5 text-[var(--ui-button-icon-global-icon-color-idle)] outline-none hover:bg-[var(--ui-button-icon-global-container-color-hover)] active:bg-[var(--ui-button-icon-global-container-color-active)] focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] [&_svg]:size-4 [&_svg]:shrink-0\"\n >\n <TimesIcon />\n </button>\n )}\n </div>\n\n {hasMessage && (\n <p\n id={messageId}\n className={cn(\n 'text-xs leading-4',\n hasError\n ? 'text-[var(--ui-input-text-error-msg-error-color)]'\n : disabled\n ? 'text-[var(--ui-input-text-normal-description-color-disabled)]'\n : 'text-[var(--ui-input-text-normal-description-color-idle)]'\n )}\n >\n {message}\n </p>\n )}\n </div>\n );\n }\n);\nInputText.displayName = 'InputText';\n\nexport { InputText };\n"],"names":["InputText","React","className","id","label","required","description","error","clearable","onClear","disabled","value","props","ref","reactId","inputId","messageId","hasError","hasValue","showClear","message","hasMessage","jsxs","cn","jsx","InputBox","TimesIcon"],"mappings":";;;;;AAqCA,MAAMA,IAAYC,EAAM;AAAA,EACtB,CACE;AAAA,IACE,WAAAC;AAAA,IACA,IAAAC;AAAA,IACA,OAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAMC,IAAUb,EAAM,MAAA,GAChBc,IAAUZ,KAAMW,GAChBE,IAAY,GAAGD,CAAO,YAEtBE,IAAWV,KAAS,QAAQA,MAAU,IACtCW,IAAWP,KAAS,QAAQA,MAAU,IACtCQ,IAAY,EAAQX,KAAcU,KAAY,CAACR,GAC/CU,IAAUH,IAAWV,IAAQD,GAC7Be,IAAaD,KAAW,QAAQA,MAAY;AAElD,WACE,gBAAAE,EAAC,OAAA,EAAI,WAAU,gIACZ,UAAA;AAAA,MAAAlB,KAAS,QAAQA,MAAU,MAC1B,gBAAAkB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASP;AAAA,UACT,WAAWQ;AAAA,YACT;AAAA,YACAb,IACI,4DACA;AAAA,UAAA;AAAA,UAGL,UAAA;AAAA,YAAAN;AAAA,YACAC,KACC,gBAAAmB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAY;AAAA,gBACZ,WAAU;AAAA,gBACX,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UAED;AAAA,QAAA;AAAA,MAAA;AAAA,MAKN,gBAAAF,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAACC;AAAA,UAAA;AAAA,YACC,KAAAZ;AAAA,YACA,IAAIE;AAAA,YACJ,UAAAL;AAAA,YACA,OAAAC;AAAA,YACA,gBAAcM,KAAY;AAAA,YAC1B,iBAAeZ,KAAY;AAAA,YAC3B,oBAAkBgB,IAAaL,IAAY;AAAA,YAC3C,WAAWO,EAAGJ,KAAa,QAAQjB,CAAS;AAAA,YAC3C,GAAGU;AAAA,UAAA;AAAA,QAAA;AAAA,QAELO,KACC,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAASf;AAAA,YACT,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,4BAACiB,GAAA,CAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACb,GAEJ;AAAA,MAECL,KACC,gBAAAG;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAIR;AAAA,UACJ,WAAWO;AAAA,YACT;AAAA,YACAN,IACI,sDACAP,IACE,kEACA;AAAA,UAAA;AAAA,UAGP,UAAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GAEJ;AAAA,EAEJ;AACF;AACApB,EAAU,cAAc;"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { jsx as e, jsxs as P } from "react/jsx-runtime";
|
|
2
|
+
import * as d from "react";
|
|
3
|
+
import { cva as W } from "../../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
|
|
4
|
+
import { ComposedChart as Y, LineChart as q, CartesianGrid as H, XAxis as J, YAxis as K, Area as Q, Line as U } from "recharts";
|
|
5
|
+
import { cn as Z } from "../../../lib/utils.js";
|
|
6
|
+
import { ChartContainer as w, ChartTooltip as y, ChartTooltipContent as b, ChartLegend as x, ChartLegendContent as _ } from "../chart/chart.js";
|
|
7
|
+
const tt = W("", {
|
|
8
|
+
variants: {
|
|
9
|
+
curve: {
|
|
10
|
+
linear: "",
|
|
11
|
+
monotone: "",
|
|
12
|
+
step: ""
|
|
13
|
+
},
|
|
14
|
+
lineStyle: {
|
|
15
|
+
solid: "",
|
|
16
|
+
dashed: ""
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
curve: "monotone",
|
|
21
|
+
lineStyle: "solid"
|
|
22
|
+
}
|
|
23
|
+
}), B = "__band_";
|
|
24
|
+
function C(n) {
|
|
25
|
+
return n == null ? void 0 : n.filter(
|
|
26
|
+
(r) => !String(r.dataKey).startsWith(B)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
function et(n) {
|
|
30
|
+
return function(i) {
|
|
31
|
+
const l = {
|
|
32
|
+
...i,
|
|
33
|
+
payload: C(i.payload)
|
|
34
|
+
};
|
|
35
|
+
return typeof n == "function" ? d.createElement(
|
|
36
|
+
n,
|
|
37
|
+
l
|
|
38
|
+
) : d.cloneElement(n, l);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const at = d.forwardRef(
|
|
42
|
+
({
|
|
43
|
+
className: n,
|
|
44
|
+
config: r,
|
|
45
|
+
data: i,
|
|
46
|
+
dataKeys: l,
|
|
47
|
+
comparisonKeys: c,
|
|
48
|
+
deltaBands: D,
|
|
49
|
+
xKey: $,
|
|
50
|
+
xAxisLabel: f,
|
|
51
|
+
yAxisLabel: m,
|
|
52
|
+
yUnit: k,
|
|
53
|
+
curve: s = "monotone",
|
|
54
|
+
lineStyle: h = "solid",
|
|
55
|
+
strokeWidth: E = 2,
|
|
56
|
+
showDots: A = !0,
|
|
57
|
+
connectNulls: L = !1,
|
|
58
|
+
showGrid: M = !0,
|
|
59
|
+
showTooltip: R = !0,
|
|
60
|
+
showLegend: S = !0,
|
|
61
|
+
tooltipContent: u,
|
|
62
|
+
...N
|
|
63
|
+
}, j) => {
|
|
64
|
+
const F = h === "dashed" ? "5 5" : void 0, T = d.useMemo(
|
|
65
|
+
() => u ? et(u) : void 0,
|
|
66
|
+
[u]
|
|
67
|
+
), I = f ? { value: f, position: "insideBottom", offset: 0 } : void 0, O = m ? {
|
|
68
|
+
value: m,
|
|
69
|
+
angle: -90,
|
|
70
|
+
position: "insideLeft",
|
|
71
|
+
style: { textAnchor: "middle" }
|
|
72
|
+
} : void 0, o = (D ?? []).map(([t, a], p) => ({
|
|
73
|
+
field: `${B}${p}`,
|
|
74
|
+
current: t,
|
|
75
|
+
comparison: a
|
|
76
|
+
})), V = o.length ? i.map((t) => {
|
|
77
|
+
const a = { ...t };
|
|
78
|
+
for (const { field: p, current: z, comparison: G } of o) {
|
|
79
|
+
const v = t[z], g = t[G];
|
|
80
|
+
a[p] = typeof v == "number" && typeof g == "number" ? [Math.min(v, g), Math.max(v, g)] : void 0;
|
|
81
|
+
}
|
|
82
|
+
return a;
|
|
83
|
+
}) : i, X = o.length > 0 ? Y : q;
|
|
84
|
+
return /* @__PURE__ */ e(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
ref: j,
|
|
88
|
+
"data-curve": s,
|
|
89
|
+
"data-line-style": h,
|
|
90
|
+
className: Z(tt({ curve: s, lineStyle: h }), n),
|
|
91
|
+
...N,
|
|
92
|
+
children: /* @__PURE__ */ e(
|
|
93
|
+
w,
|
|
94
|
+
{
|
|
95
|
+
config: r,
|
|
96
|
+
className: "size-full [&_.recharts-label]:fill-foreground",
|
|
97
|
+
children: /* @__PURE__ */ P(X, { data: V, children: [
|
|
98
|
+
M && /* @__PURE__ */ e(H, { vertical: !1 }),
|
|
99
|
+
/* @__PURE__ */ e(
|
|
100
|
+
J,
|
|
101
|
+
{
|
|
102
|
+
dataKey: $,
|
|
103
|
+
type: "category",
|
|
104
|
+
tickLine: !1,
|
|
105
|
+
axisLine: !1,
|
|
106
|
+
tickMargin: 8,
|
|
107
|
+
height: f ? 48 : void 0,
|
|
108
|
+
label: I
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
/* @__PURE__ */ e(
|
|
112
|
+
K,
|
|
113
|
+
{
|
|
114
|
+
type: "number",
|
|
115
|
+
tickLine: !1,
|
|
116
|
+
axisLine: !1,
|
|
117
|
+
unit: k,
|
|
118
|
+
width: m ? 72 : void 0,
|
|
119
|
+
label: O
|
|
120
|
+
}
|
|
121
|
+
),
|
|
122
|
+
R && (T ? (
|
|
123
|
+
// Strips the synthetic delta bands before the caller's tooltip
|
|
124
|
+
// sees them — the `__band_*` series feed the Areas, not the
|
|
125
|
+
// tooltip (a no-op when no bands are configured).
|
|
126
|
+
/* @__PURE__ */ e(y, { content: T })
|
|
127
|
+
) : o.length > 0 ? /* @__PURE__ */ e(
|
|
128
|
+
y,
|
|
129
|
+
{
|
|
130
|
+
content: (t) => /* @__PURE__ */ e(
|
|
131
|
+
b,
|
|
132
|
+
{
|
|
133
|
+
active: t.active,
|
|
134
|
+
label: t.label,
|
|
135
|
+
payload: C(
|
|
136
|
+
t.payload
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
) : /* @__PURE__ */ e(y, { content: /* @__PURE__ */ e(b, {}) })),
|
|
142
|
+
S && (o.length > 0 ? /* @__PURE__ */ e(
|
|
143
|
+
x,
|
|
144
|
+
{
|
|
145
|
+
content: (t) => /* @__PURE__ */ e(
|
|
146
|
+
_,
|
|
147
|
+
{
|
|
148
|
+
verticalAlign: t.verticalAlign,
|
|
149
|
+
payload: C(
|
|
150
|
+
t.payload
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
) : /* @__PURE__ */ e(x, { content: /* @__PURE__ */ e(_, {}) })),
|
|
156
|
+
o.map(({ field: t, current: a }) => /* @__PURE__ */ e(
|
|
157
|
+
Q,
|
|
158
|
+
{
|
|
159
|
+
dataKey: t,
|
|
160
|
+
type: s ?? "monotone",
|
|
161
|
+
stroke: "none",
|
|
162
|
+
fill: `var(--color-${a})`,
|
|
163
|
+
fillOpacity: 0.12,
|
|
164
|
+
connectNulls: L,
|
|
165
|
+
dot: !1,
|
|
166
|
+
activeDot: !1,
|
|
167
|
+
isAnimationActive: !1,
|
|
168
|
+
legendType: "none",
|
|
169
|
+
tooltipType: "none"
|
|
170
|
+
},
|
|
171
|
+
t
|
|
172
|
+
)),
|
|
173
|
+
l.map((t) => {
|
|
174
|
+
const a = c == null ? void 0 : c.includes(t);
|
|
175
|
+
return /* @__PURE__ */ e(
|
|
176
|
+
U,
|
|
177
|
+
{
|
|
178
|
+
type: s ?? "monotone",
|
|
179
|
+
dataKey: t,
|
|
180
|
+
stroke: `var(--color-${t})`,
|
|
181
|
+
strokeWidth: E,
|
|
182
|
+
strokeDasharray: a ? "5 5" : F,
|
|
183
|
+
strokeOpacity: a ? 0.5 : void 0,
|
|
184
|
+
dot: !a && A ? { r: 3 } : !1,
|
|
185
|
+
activeDot: !a && A ? { r: 5 } : !1,
|
|
186
|
+
connectNulls: L,
|
|
187
|
+
isAnimationActive: !1
|
|
188
|
+
},
|
|
189
|
+
t
|
|
190
|
+
);
|
|
191
|
+
})
|
|
192
|
+
] })
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
at.displayName = "LineChart";
|
|
200
|
+
export {
|
|
201
|
+
at as LineChart,
|
|
202
|
+
et as createBandStrippedTooltip,
|
|
203
|
+
C as dropBandSeries,
|
|
204
|
+
tt as lineChartVariants
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=line-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-chart.js","sources":["../../../../src/components/ui/line-chart/line-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n Area,\n CartesianGrid,\n ComposedChart,\n Line,\n LineChart as RechartsLineChart,\n XAxis,\n YAxis,\n} from 'recharts';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n type ChartLegendContentProps,\n type ChartTooltipContentProps,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives. The two CVA\n// axes are the design's Line-chart variant set: `curve` (how the segments\n// interpolate between points — straight, smoothed, or stepped) and `lineStyle`\n// (a solid or dashed stroke). \"single\" vs \"multi\" line is not a variant — it\n// falls out of how many `dataKeys` the caller plots. The classes stay empty\n// because recharts' SVG — not CSS — draws the lines: `curve` drives each\n// `<Line type>` and `lineStyle` drives its `strokeDasharray`. CVA is kept so the\n// variant set is a first-class, spec-conformant part of the API (matched against\n// ui-spec's api.yaml enums) and exposed via `VariantProps`; the resolved values\n// are also mirrored onto `data-curve` / `data-line-style` for styling hooks and\n// tests.\nconst lineChartVariants = cva('', {\n variants: {\n curve: {\n linear: '',\n monotone: '',\n step: '',\n },\n lineStyle: {\n solid: '',\n dashed: '',\n },\n },\n defaultVariants: {\n curve: 'monotone',\n lineStyle: 'solid',\n },\n});\n\n// Reserved field prefix for the synthetic delta-band range series. Each band\n// mints one `__band_<n>` field that feeds an <Area>; it must never surface in\n// the tooltip or legend (those describe only real, caller-supplied series).\nconst BAND_FIELD_PREFIX = '__band_';\n\n/**\n * Drop the synthetic delta-band range series from a recharts tooltip/legend\n * payload, keeping the real series (and their order). recharts already excludes\n * the band via `legendType`/`tooltipType=\"none\"`, so this is a second, explicit\n * guard — hence it's unit-tested rather than relying on that behavior.\n */\nexport function dropBandSeries<T extends { dataKey?: unknown }>(\n payload: readonly T[] | undefined\n): T[] | undefined {\n return payload?.filter(\n (item) => !String(item.dataKey).startsWith(BAND_FIELD_PREFIX)\n );\n}\n\ntype TooltipContentType = NonNullable<\n React.ComponentProps<typeof ChartTooltip>['content']\n>;\ntype TooltipContentFn = Extract<TooltipContentType, (...args: never[]) => unknown>;\ntype TooltipRenderProps = Parameters<TooltipContentFn>[0];\n\n/**\n * Wrap a caller-supplied `tooltipContent` so the synthetic delta bands are\n * stripped from the payload before it renders, while preserving recharts' own\n * mount semantics — a function is mounted via `createElement` (its own component\n * identity + hook state), an element via `cloneElement`. This mirrors what the\n * pass-through charts get by handing `content` straight to recharts, so a\n * function-form tooltip keeps its state across re-renders here too. The returned\n * component is a stable content type (memoize it on `tooltipContent`).\n */\nexport function createBandStrippedTooltip(tooltipContent: TooltipContentType) {\n return function BandStrippedTooltip(props: TooltipRenderProps) {\n const merged = {\n ...props,\n payload: dropBandSeries(props.payload),\n } as TooltipRenderProps;\n return typeof tooltipContent === 'function'\n ? React.createElement(\n tooltipContent as React.FunctionComponent<TooltipRenderProps>,\n merged\n )\n : React.cloneElement(tooltipContent, merged);\n };\n}\n\nexport interface LineChartProps\n extends Omit<React.ComponentProps<'div'>, 'children'>,\n VariantProps<typeof lineChartVariants> {\n /** Row-per-point data. Each object holds the category key + one numeric field per series (`null` breaks the line unless `connectNulls`). */\n data: ReadonlyArray<Record<string, string | number | null>>;\n /**\n * Per-series map of `label` / `color` (imported from the shared `Chart`\n * primitives). Series colors are caller-supplied — reference an existing\n * semantic `--ui-*` token; there is no chart palette tier yet.\n */\n config: ChartConfig;\n /** Series to plot — one `<Line>` per key. Each must exist in `config` and in every data row. */\n dataKeys: string[];\n /**\n * Subset of `dataKeys` to render as comparison/trend overlays (e.g. a\n * previous quarter or year) — dashed, dimmed, and dot-less, so they read as\n * secondary to the current-period lines. Keeps each series' own `config` color.\n */\n comparisonKeys?: string[];\n /**\n * Pairs of `[currentKey, comparisonKey]` to shade a delta band between — a\n * dimmed area filling the gap between the two series at each point,\n * visualizing the QoQ/YoY difference. Tinted with the first key's `config`\n * color. Rows where either value isn't numeric are left un-banded.\n *\n * Each pair mints an internal `__band_<n>` field (kept out of the tooltip and\n * legend), so avoid data/`config` keys with that reserved prefix.\n */\n deltaBands?: Array<[string, string]>;\n /** Category axis key (the shared dimension across rows, e.g. `\"month\"`). */\n xKey: string;\n /** Title rendered beneath the horizontal (X) axis. */\n xAxisLabel?: string;\n /** Title rendered beside the vertical (Y) axis (rotated). */\n yAxisLabel?: string;\n /** Unit suffix appended to Y-axis tick values (recharts `unit`; the X axis is categorical). */\n yUnit?: string;\n /** Stroke width of each line. */\n strokeWidth?: number;\n /** Render a dot at each data point. */\n showDots?: boolean;\n /** Bridge `null` gaps in the data instead of breaking the line. */\n connectNulls?: boolean;\n showGrid?: boolean;\n showTooltip?: boolean;\n showLegend?: boolean;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` /\n * `indicator` — to customize formatting, per-series rows, or extra fields\n * without composing recharts yourself. Ignored when `showTooltip` is false.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n}\n\nconst LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(\n (\n {\n className,\n config,\n data,\n dataKeys,\n comparisonKeys,\n deltaBands,\n xKey,\n xAxisLabel,\n yAxisLabel,\n yUnit,\n curve = 'monotone',\n lineStyle = 'solid',\n strokeWidth = 2,\n showDots = true,\n connectNulls = false,\n showGrid = true,\n showTooltip = true,\n showLegend = true,\n tooltipContent,\n ...props\n },\n ref\n ) => {\n const dashArray = lineStyle === 'dashed' ? '5 5' : undefined;\n\n // Memoized so recharts sees a stable content type across renders — a fresh\n // wrapper each render would remount the caller's tooltip and reset its state.\n const customTooltip = React.useMemo(\n () =>\n tooltipContent ? createBandStrippedTooltip(tooltipContent) : undefined,\n [tooltipContent]\n );\n\n // Axis titles: the X title sits below the ticks; the Y title is rotated in\n // the left gutter. Passed to recharts' native `label` (themed via the\n // `.recharts-label` fill selector on the container).\n const xAxisTitle = xAxisLabel\n ? { value: xAxisLabel, position: 'insideBottom' as const, offset: 0 }\n : undefined;\n const yAxisTitle = yAxisLabel\n ? {\n value: yAxisLabel,\n angle: -90,\n position: 'insideLeft' as const,\n style: { textAnchor: 'middle' as const },\n }\n : undefined;\n\n // Each delta band becomes a synthetic `[min, max]` range field per row that\n // a recharts <Area> shades. Rows where either series isn't numeric are left\n // un-banded (the area breaks there).\n const bands = (deltaBands ?? []).map(([current, comparison], index) => ({\n field: `${BAND_FIELD_PREFIX}${index}`,\n current,\n comparison,\n }));\n const chartData = bands.length\n ? data.map((row) => {\n const augmented: Record<string, unknown> = { ...row };\n for (const { field, current, comparison } of bands) {\n const a = row[current];\n const b = row[comparison];\n augmented[field] =\n typeof a === 'number' && typeof b === 'number'\n ? [Math.min(a, b), Math.max(a, b)]\n : undefined;\n }\n return augmented;\n })\n : data;\n\n // Only a delta band needs an <Area>, which recharts renders under\n // ComposedChart, not LineChart. Escalate to ComposedChart only then, so\n // plain line charts keep the LineChart base (and their baselines) untouched.\n const RootChart = bands.length > 0 ? ComposedChart : RechartsLineChart;\n\n return (\n <div\n ref={ref}\n data-curve={curve}\n data-line-style={lineStyle}\n className={cn(lineChartVariants({ curve, lineStyle }), className)}\n {...props}\n >\n <ChartContainer\n config={config}\n className=\"size-full [&_.recharts-label]:fill-foreground\"\n >\n <RootChart data={chartData as readonly unknown[]}>\n {showGrid && <CartesianGrid vertical={false} />}\n <XAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tickMargin={8}\n height={xAxisLabel ? 48 : undefined}\n label={xAxisTitle}\n />\n <YAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n unit={yUnit}\n width={yAxisLabel ? 72 : undefined}\n label={yAxisTitle}\n />\n {showTooltip &&\n (customTooltip ? (\n // Strips the synthetic delta bands before the caller's tooltip\n // sees them — the `__band_*` series feed the Areas, not the\n // tooltip (a no-op when no bands are configured).\n <ChartTooltip content={customTooltip} />\n ) : bands.length > 0 ? (\n <ChartTooltip\n content={(props) => (\n <ChartTooltipContent\n active={props.active}\n label={props.label}\n payload={\n dropBandSeries(\n props.payload\n ) as ChartTooltipContentProps['payload']\n }\n />\n )}\n />\n ) : (\n <ChartTooltip content={<ChartTooltipContent />} />\n ))}\n {showLegend &&\n (bands.length > 0 ? (\n <ChartLegend\n content={(props) => (\n <ChartLegendContent\n verticalAlign={props.verticalAlign}\n payload={\n dropBandSeries(\n props.payload\n ) as ChartLegendContentProps['payload']\n }\n />\n )}\n />\n ) : (\n <ChartLegend content={<ChartLegendContent />} />\n ))}\n {/* Delta bands render before the lines so the lines draw on top. */}\n {bands.map(({ field, current }) => (\n <Area\n key={field}\n dataKey={field}\n type={curve ?? 'monotone'}\n stroke=\"none\"\n fill={`var(--color-${current})`}\n fillOpacity={0.12}\n connectNulls={connectNulls}\n dot={false}\n activeDot={false}\n isAnimationActive={false}\n legendType=\"none\"\n tooltipType=\"none\"\n />\n ))}\n {dataKeys.map((key) => {\n // Comparison series read as secondary: always dashed, dimmed, and\n // dot-less, regardless of the global lineStyle / showDots.\n const isComparison = comparisonKeys?.includes(key);\n return (\n <Line\n key={key}\n type={curve ?? 'monotone'}\n dataKey={key}\n stroke={`var(--color-${key})`}\n strokeWidth={strokeWidth}\n strokeDasharray={isComparison ? '5 5' : dashArray}\n strokeOpacity={isComparison ? 0.5 : undefined}\n dot={!isComparison && showDots ? { r: 3 } : false}\n activeDot={!isComparison && showDots ? { r: 5 } : false}\n connectNulls={connectNulls}\n isAnimationActive={false}\n />\n );\n })}\n </RootChart>\n </ChartContainer>\n </div>\n );\n }\n);\nLineChart.displayName = 'LineChart';\n\nexport { LineChart, lineChartVariants };\n"],"names":["lineChartVariants","cva","BAND_FIELD_PREFIX","dropBandSeries","payload","item","createBandStrippedTooltip","tooltipContent","props","merged","React","LineChart","className","config","data","dataKeys","comparisonKeys","deltaBands","xKey","xAxisLabel","yAxisLabel","yUnit","curve","lineStyle","strokeWidth","showDots","connectNulls","showGrid","showTooltip","showLegend","ref","dashArray","customTooltip","xAxisTitle","yAxisTitle","bands","current","comparison","index","chartData","row","augmented","field","a","b","RootChart","ComposedChart","RechartsLineChart","jsx","cn","ChartContainer","jsxs","CartesianGrid","XAxis","YAxis","ChartTooltip","ChartTooltipContent","ChartLegend","ChartLegendContent","Area","key","isComparison","Line"],"mappings":";;;;;;AAqCA,MAAMA,KAAoBC,EAAI,IAAI;AAAA,EAChC,UAAU;AAAA,IACR,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,IAAA;AAAA,IAER,WAAW;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA;AAAA,EACV;AAAA,EAEF,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,WAAW;AAAA,EAAA;AAEf,CAAC,GAKKC,IAAoB;AAQnB,SAASC,EACdC,GACiB;AACjB,SAAOA,KAAA,gBAAAA,EAAS;AAAA,IACd,CAACC,MAAS,CAAC,OAAOA,EAAK,OAAO,EAAE,WAAWH,CAAiB;AAAA;AAEhE;AAiBO,SAASI,GAA0BC,GAAoC;AAC5E,SAAO,SAA6BC,GAA2B;AAC7D,UAAMC,IAAS;AAAA,MACb,GAAGD;AAAA,MACH,SAASL,EAAeK,EAAM,OAAO;AAAA,IAAA;AAEvC,WAAO,OAAOD,KAAmB,aAC7BG,EAAM;AAAA,MACJH;AAAA,MACAE;AAAA,IAAA,IAEFC,EAAM,aAAaH,GAAgBE,CAAM;AAAA,EAC/C;AACF;AAyDA,MAAME,KAAYD,EAAM;AAAA,EACtB,CACE;AAAA,IACE,WAAAE;AAAA,IACA,QAAAC;AAAA,IACA,MAAAC;AAAA,IACA,UAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,MAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,OAAAC;AAAA,IACA,OAAAC,IAAQ;AAAA,IACR,WAAAC,IAAY;AAAA,IACZ,aAAAC,IAAc;AAAA,IACd,UAAAC,IAAW;AAAA,IACX,cAAAC,IAAe;AAAA,IACf,UAAAC,IAAW;AAAA,IACX,aAAAC,IAAc;AAAA,IACd,YAAAC,IAAa;AAAA,IACb,gBAAAtB;AAAA,IACA,GAAGC;AAAA,EAAA,GAELsB,MACG;AACH,UAAMC,IAAYR,MAAc,WAAW,QAAQ,QAI7CS,IAAgBtB,EAAM;AAAA,MAC1B,MACEH,IAAiBD,GAA0BC,CAAc,IAAI;AAAA,MAC/D,CAACA,CAAc;AAAA,IAAA,GAMX0B,IAAad,IACf,EAAE,OAAOA,GAAY,UAAU,gBAAyB,QAAQ,EAAA,IAChE,QACEe,IAAad,IACf;AAAA,MACE,OAAOA;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,EAAE,YAAY,SAAA;AAAA,IAAkB,IAEzC,QAKEe,KAASlB,KAAc,IAAI,IAAI,CAAC,CAACmB,GAASC,CAAU,GAAGC,OAAW;AAAA,MACtE,OAAO,GAAGpC,CAAiB,GAAGoC,CAAK;AAAA,MACnC,SAAAF;AAAA,MACA,YAAAC;AAAA,IAAA,EACA,GACIE,IAAYJ,EAAM,SACpBrB,EAAK,IAAI,CAAC0B,MAAQ;AAChB,YAAMC,IAAqC,EAAE,GAAGD,EAAA;AAChD,iBAAW,EAAE,OAAAE,GAAO,SAAAN,GAAS,YAAAC,EAAA,KAAgBF,GAAO;AAClD,cAAMQ,IAAIH,EAAIJ,CAAO,GACfQ,IAAIJ,EAAIH,CAAU;AACxB,QAAAI,EAAUC,CAAK,IACb,OAAOC,KAAM,YAAY,OAAOC,KAAM,WAClC,CAAC,KAAK,IAAID,GAAGC,CAAC,GAAG,KAAK,IAAID,GAAGC,CAAC,CAAC,IAC/B;AAAA,MACR;AACA,aAAOH;AAAA,IACT,CAAC,IACD3B,GAKE+B,IAAYV,EAAM,SAAS,IAAIW,IAAgBC;AAErD,WACE,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAlB;AAAA,QACA,cAAYR;AAAA,QACZ,mBAAiBC;AAAA,QACjB,WAAW0B,EAAGjD,GAAkB,EAAE,OAAAsB,GAAO,WAAAC,EAAA,CAAW,GAAGX,CAAS;AAAA,QAC/D,GAAGJ;AAAA,QAEJ,UAAA,gBAAAwC;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,QAAArC;AAAA,YACA,WAAU;AAAA,YAEV,UAAA,gBAAAsC,EAACN,GAAA,EAAU,MAAMN,GACd,UAAA;AAAA,cAAAZ,KAAY,gBAAAqB,EAACI,GAAA,EAAc,UAAU,GAAA,CAAO;AAAA,cAC7C,gBAAAJ;AAAA,gBAACK;AAAA,gBAAA;AAAA,kBACC,SAASnC;AAAA,kBACT,MAAK;AAAA,kBACL,UAAU;AAAA,kBACV,UAAU;AAAA,kBACV,YAAY;AAAA,kBACZ,QAAQC,IAAa,KAAK;AAAA,kBAC1B,OAAOc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAET,gBAAAe;AAAA,gBAACM;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,UAAU;AAAA,kBACV,UAAU;AAAA,kBACV,MAAMjC;AAAA,kBACN,OAAOD,IAAa,KAAK;AAAA,kBACzB,OAAOc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAERN,MACEI;AAAA;AAAA;AAAA;AAAA,gBAIC,gBAAAgB,EAACO,GAAA,EAAa,SAASvB,EAAA,CAAe;AAAA,kBACpCG,EAAM,SAAS,IACjB,gBAAAa;AAAA,gBAACO;AAAA,gBAAA;AAAA,kBACC,SAAS,CAAC/C,MACR,gBAAAwC;AAAA,oBAACQ;AAAA,oBAAA;AAAA,sBACC,QAAQhD,EAAM;AAAA,sBACd,OAAOA,EAAM;AAAA,sBACb,SACEL;AAAA,wBACEK,EAAM;AAAA,sBAAA;AAAA,oBACR;AAAA,kBAAA;AAAA,gBAEJ;AAAA,cAAA,IAIJ,gBAAAwC,EAACO,GAAA,EAAa,SAAS,gBAAAP,EAACQ,KAAoB,EAAA,CAAI;AAAA,cAEnD3B,MACEM,EAAM,SAAS,IACd,gBAAAa;AAAA,gBAACS;AAAA,gBAAA;AAAA,kBACC,SAAS,CAACjD,MACR,gBAAAwC;AAAA,oBAACU;AAAA,oBAAA;AAAA,sBACC,eAAelD,EAAM;AAAA,sBACrB,SACEL;AAAA,wBACEK,EAAM;AAAA,sBAAA;AAAA,oBACR;AAAA,kBAAA;AAAA,gBAEJ;AAAA,cAAA,IAIJ,gBAAAwC,EAACS,GAAA,EAAY,SAAS,gBAAAT,EAACU,KAAmB,EAAA,CAAI;AAAA,cAGjDvB,EAAM,IAAI,CAAC,EAAE,OAAAO,GAAO,SAAAN,QACnB,gBAAAY;AAAA,gBAACW;AAAA,gBAAA;AAAA,kBAEC,SAASjB;AAAA,kBACT,MAAMpB,KAAS;AAAA,kBACf,QAAO;AAAA,kBACP,MAAM,eAAec,CAAO;AAAA,kBAC5B,aAAa;AAAA,kBACb,cAAAV;AAAA,kBACA,KAAK;AAAA,kBACL,WAAW;AAAA,kBACX,mBAAmB;AAAA,kBACnB,YAAW;AAAA,kBACX,aAAY;AAAA,gBAAA;AAAA,gBAXPgB;AAAA,cAAA,CAaR;AAAA,cACA3B,EAAS,IAAI,CAAC6C,MAAQ;AAGrB,sBAAMC,IAAe7C,KAAA,gBAAAA,EAAgB,SAAS4C;AAC9C,uBACE,gBAAAZ;AAAA,kBAACc;AAAA,kBAAA;AAAA,oBAEC,MAAMxC,KAAS;AAAA,oBACf,SAASsC;AAAA,oBACT,QAAQ,eAAeA,CAAG;AAAA,oBAC1B,aAAApC;AAAA,oBACA,iBAAiBqC,IAAe,QAAQ9B;AAAA,oBACxC,eAAe8B,IAAe,MAAM;AAAA,oBACpC,KAAK,CAACA,KAAgBpC,IAAW,EAAE,GAAG,MAAM;AAAA,oBAC5C,WAAW,CAACoC,KAAgBpC,IAAW,EAAE,GAAG,MAAM;AAAA,oBAClD,cAAAC;AAAA,oBACA,mBAAmB;AAAA,kBAAA;AAAA,kBAVdkC;AAAA,gBAAA;AAAA,cAaX,CAAC;AAAA,YAAA,EAAA,CACH;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAGN;AACF;AACAjD,GAAU,cAAc;"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { jsxs as c, Fragment as s, jsx as
|
|
2
|
-
import * as
|
|
1
|
+
import { jsxs as c, Fragment as s, jsx as v } from "react/jsx-runtime";
|
|
2
|
+
import * as d from "react";
|
|
3
3
|
import { mergeProps as x } from "@base-ui/react/merge-props";
|
|
4
4
|
import { useRender as m } from "@base-ui/react/use-render";
|
|
5
5
|
import { SquareArrowUpRightIcon as u } from "@acronis-platform/icons-react/stroke-mono";
|
|
6
6
|
import { cn as g } from "../../../lib/utils.js";
|
|
7
|
-
const p =
|
|
7
|
+
const p = d.forwardRef(
|
|
8
8
|
({ className: i, external: o, disabled: e, href: r, children: t, render: a, ...n }, l) => m({
|
|
9
9
|
render: a,
|
|
10
10
|
ref: l,
|
|
@@ -12,7 +12,7 @@ const p = v.forwardRef(
|
|
|
12
12
|
props: x(
|
|
13
13
|
{
|
|
14
14
|
className: g(
|
|
15
|
-
"inline-flex items-center gap-[var(--ui-link-global-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [
|
|
15
|
+
"inline-flex items-center gap-[var(--ui-link-global-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [&_svg]:size-4 [&_svg]:shrink-0",
|
|
16
16
|
"text-[var(--ui-link-normal-text-color-idle)] [text-decoration:var(--ui-link-global-text-decoration-idle)] [&_svg]:text-[var(--ui-link-normal-external-icon-color-idle)]",
|
|
17
17
|
"hover:text-[var(--ui-link-normal-text-color-hover)] hover:[text-decoration:var(--ui-link-global-text-decoration-hover)] hover:[&_svg]:text-[var(--ui-link-normal-external-icon-color-hover)]",
|
|
18
18
|
"active:text-[var(--ui-link-normal-text-color-active)] active:[text-decoration:var(--ui-link-global-text-decoration-active)] active:[&_svg]:text-[var(--ui-link-normal-external-icon-color-active)]",
|
|
@@ -25,7 +25,7 @@ const p = v.forwardRef(
|
|
|
25
25
|
tabIndex: e ? -1 : void 0,
|
|
26
26
|
children: /* @__PURE__ */ c(s, { children: [
|
|
27
27
|
t,
|
|
28
|
-
o && /* @__PURE__ */
|
|
28
|
+
o && /* @__PURE__ */ v(u, { size: 16 })
|
|
29
29
|
] })
|
|
30
30
|
},
|
|
31
31
|
n
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sources":["../../../../src/components/ui/link/link.tsx"],"sourcesContent":["import * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { SquareArrowUpRightIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Mirrors the Figma \"Link\" component: an inline text link (semibold, 14/24) with an\n// optional trailing external-link icon (`external`). Themed by the `--ui-link-*`\n// tier — each state wires its own text color (`--ui-link-normal-text-color-*`), text\n// decoration (`--ui-link-global-text-decoration-*`; underline on hover only) and\n// external-icon color (`--ui-link-normal-external-icon-color-*`, kept separate from\n// the text per the tier). The tier also exposes an `inverse` set\n// (`--ui-link-inverse-*`) for links on dark/brand surfaces; it is not wired here yet.\n// Focus paints a 3px `--ui-focus-primary` ring. Polymorphic via Base UI `useRender`\n// — pass `render` to render a router `Link` instead of the default `<a>`. `disabled`\n// makes it inert: disabled color, removed from the tab order, no navigation.\n//\n// The Figma container has a fixed 32px height for grid alignment\n// (`--ui-link-global-container-height`); it is intentionally NOT applied here so the\n// link flows inline within prose.\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n /** Append a trailing external-link icon (e.g. for links that leave the app). */\n external?: boolean;\n /** Render the link inert: disabled color, removed from the tab order, no navigation. */\n disabled?: boolean;\n /**\n * Replace the rendered `<a>` with another element or component (Base UI\n * composition) — e.g. a router `Link`. Props and class names are merged onto it.\n */\n render?: useRender.RenderProp;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, external, disabled, href, children, render, ...props }, ref) =>\n useRender({\n render,\n ref,\n defaultTagName: 'a',\n props: mergeProps<'a'>(\n {\n className: cn(\n 'inline-flex items-center gap-[var(--ui-link-global-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [
|
|
1
|
+
{"version":3,"file":"link.js","sources":["../../../../src/components/ui/link/link.tsx"],"sourcesContent":["import * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { SquareArrowUpRightIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Mirrors the Figma \"Link\" component: an inline text link (semibold, 14/24) with an\n// optional trailing external-link icon (`external`). Themed by the `--ui-link-*`\n// tier — each state wires its own text color (`--ui-link-normal-text-color-*`), text\n// decoration (`--ui-link-global-text-decoration-*`; underline on hover only) and\n// external-icon color (`--ui-link-normal-external-icon-color-*`, kept separate from\n// the text per the tier). The tier also exposes an `inverse` set\n// (`--ui-link-inverse-*`) for links on dark/brand surfaces; it is not wired here yet.\n// Focus paints a 3px `--ui-focus-primary` ring. Polymorphic via Base UI `useRender`\n// — pass `render` to render a router `Link` instead of the default `<a>`. `disabled`\n// makes it inert: disabled color, removed from the tab order, no navigation.\n//\n// The Figma container has a fixed 32px height for grid alignment\n// (`--ui-link-global-container-height`); it is intentionally NOT applied here so the\n// link flows inline within prose.\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n /** Append a trailing external-link icon (e.g. for links that leave the app). */\n external?: boolean;\n /** Render the link inert: disabled color, removed from the tab order, no navigation. */\n disabled?: boolean;\n /**\n * Replace the rendered `<a>` with another element or component (Base UI\n * composition) — e.g. a router `Link`. Props and class names are merged onto it.\n */\n render?: useRender.RenderProp;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, external, disabled, href, children, render, ...props }, ref) =>\n useRender({\n render,\n ref,\n defaultTagName: 'a',\n props: mergeProps<'a'>(\n {\n className: cn(\n 'inline-flex items-center gap-[var(--ui-link-global-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [&_svg]:size-4 [&_svg]:shrink-0',\n 'text-[var(--ui-link-normal-text-color-idle)] [text-decoration:var(--ui-link-global-text-decoration-idle)] [&_svg]:text-[var(--ui-link-normal-external-icon-color-idle)]',\n 'hover:text-[var(--ui-link-normal-text-color-hover)] hover:[text-decoration:var(--ui-link-global-text-decoration-hover)] hover:[&_svg]:text-[var(--ui-link-normal-external-icon-color-hover)]',\n 'active:text-[var(--ui-link-normal-text-color-active)] active:[text-decoration:var(--ui-link-global-text-decoration-active)] active:[&_svg]:text-[var(--ui-link-normal-external-icon-color-active)]',\n 'focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)]',\n 'aria-disabled:pointer-events-none aria-disabled:text-[var(--ui-link-normal-text-color-disabled)] aria-disabled:[text-decoration:var(--ui-link-global-text-decoration-disabled)] aria-disabled:[&_svg]:text-[var(--ui-link-normal-external-icon-color-disabled)]',\n className\n ),\n href: disabled ? undefined : href,\n 'aria-disabled': disabled || undefined,\n tabIndex: disabled ? -1 : undefined,\n children: (\n <>\n {children}\n {external && <SquareArrowUpRightIcon size={16} />}\n </>\n ),\n },\n props\n ),\n })\n);\nLink.displayName = 'Link';\n\nexport { Link };\n"],"names":["Link","React","className","external","disabled","href","children","render","props","ref","useRender","mergeProps","cn","jsxs","Fragment","jsx","SquareArrowUpRightIcon"],"mappings":";;;;;;AAiCA,MAAMA,IAAOC,EAAM;AAAA,EACjB,CAAC,EAAE,WAAAC,GAAW,UAAAC,GAAU,UAAAC,GAAU,MAAAC,GAAM,UAAAC,GAAU,QAAAC,GAAQ,GAAGC,KAASC,MACpEC,EAAU;AAAA,IACR,QAAAH;AAAA,IACA,KAAAE;AAAA,IACA,gBAAgB;AAAA,IAChB,OAAOE;AAAA,MACL;AAAA,QACE,WAAWC;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACAV;AAAA,QAAA;AAAA,QAEF,MAAME,IAAW,SAAYC;AAAA,QAC7B,iBAAiBD,KAAY;AAAA,QAC7B,UAAUA,IAAW,KAAK;AAAA,QAC1B,UACE,gBAAAS,EAAAC,GAAA,EACG,UAAA;AAAA,UAAAR;AAAA,UACAH,KAAY,gBAAAY,EAACC,GAAA,EAAuB,MAAM,GAAA,CAAI;AAAA,QAAA,EAAA,CACjD;AAAA,MAAA;AAAA,MAGJR;AAAA,IAAA;AAAA,EACF,CACD;AACL;AACAR,EAAK,cAAc;"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsxs as d, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import * as g from "react";
|
|
3
|
+
import { cva as s } from "../../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
|
|
4
|
+
import { cn as e } from "../../../lib/utils.js";
|
|
5
|
+
import { Spinner as u } from "../spinner/spinner.js";
|
|
6
|
+
const m = s("inline-flex items-center", {
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
inline: "gap-[var(--ui-loading-inline-container-gap)]",
|
|
10
|
+
onSurfacePrimary: "flex-col justify-center gap-[var(--ui-loading-element-container-gap)] rounded-lg bg-[var(--ui-loading-element-container-color-primary)] px-[var(--ui-loading-element-container-padding-x)] py-[var(--ui-loading-element-container-padding-y)]",
|
|
11
|
+
onSurfaceSecondary: "flex-col justify-center gap-[var(--ui-loading-element-container-gap)] rounded-lg bg-[var(--ui-loading-element-container-color-secondary)] px-[var(--ui-loading-element-container-padding-x)] py-[var(--ui-loading-element-container-padding-y)]",
|
|
12
|
+
onScreen: "flex-col justify-center gap-[var(--ui-loading-screen-container-gap)] rounded-lg bg-[var(--ui-loading-screen-container-color)] px-[var(--ui-loading-screen-container-padding-x)] py-[var(--ui-loading-screen-container-padding-y)]"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: "inline"
|
|
17
|
+
}
|
|
18
|
+
}), p = {
|
|
19
|
+
inline: "sm",
|
|
20
|
+
onSurfacePrimary: "lg",
|
|
21
|
+
onSurfaceSecondary: "lg",
|
|
22
|
+
onScreen: "xl"
|
|
23
|
+
}, v = {
|
|
24
|
+
inline: "text-[var(--ui-loading-inline-icon-color)]",
|
|
25
|
+
onSurfacePrimary: "text-[var(--ui-loading-element-icon-color)]",
|
|
26
|
+
onSurfaceSecondary: "text-[var(--ui-loading-element-icon-color)]",
|
|
27
|
+
onScreen: "text-[var(--ui-loading-screen-icon-color)]"
|
|
28
|
+
}, f = {
|
|
29
|
+
inline: "text-[var(--ui-loading-inline-label-color)]",
|
|
30
|
+
onSurfacePrimary: "text-[var(--ui-loading-element-label-color)]",
|
|
31
|
+
onSurfaceSecondary: "text-[var(--ui-loading-element-label-color)]",
|
|
32
|
+
onScreen: "text-[var(--ui-loading-screen-label-color)]"
|
|
33
|
+
}, x = g.forwardRef(
|
|
34
|
+
({
|
|
35
|
+
className: o,
|
|
36
|
+
variant: l = "inline",
|
|
37
|
+
hasLabel: a = !0,
|
|
38
|
+
label: i = "Data is loading…",
|
|
39
|
+
...t
|
|
40
|
+
}, c) => {
|
|
41
|
+
const n = l ?? "inline";
|
|
42
|
+
return /* @__PURE__ */ d(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
ref: c,
|
|
46
|
+
role: "status",
|
|
47
|
+
"aria-label": a ? void 0 : i,
|
|
48
|
+
className: e(m({ variant: n }), o),
|
|
49
|
+
...t,
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ r(
|
|
52
|
+
u,
|
|
53
|
+
{
|
|
54
|
+
"aria-hidden": "true",
|
|
55
|
+
size: p[n],
|
|
56
|
+
className: e("shrink-0", v[n])
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
a && /* @__PURE__ */ r(
|
|
60
|
+
"span",
|
|
61
|
+
{
|
|
62
|
+
className: e(
|
|
63
|
+
"whitespace-nowrap text-sm font-normal leading-6",
|
|
64
|
+
f[n]
|
|
65
|
+
),
|
|
66
|
+
children: i
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
x.displayName = "Loading";
|
|
75
|
+
export {
|
|
76
|
+
x as Loading,
|
|
77
|
+
m as loadingVariants
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=loading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loading.js","sources":["../../../../src/components/ui/loading/loading.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\nimport { Spinner } from '../spinner';\n\n// A composite loading indicator (spinner + optional label) for four placement\n// contexts, themed by the `--ui-loading-*` tier. Distinct from the bare `Spinner`\n// primitive (which this component reuses for its icon and which stays an\n// internal-only primitive, not re-exported — see spinner.tsx): `Spinner` is a\n// leaf atom with no label/container of its own, still used as-is by `Toast`'s\n// small inline icon. `inline` sits flush in text flow; `onSurfacePrimary`/\n// `onSurfaceSecondary` are card-like chips for placing over a primary/secondary\n// app surface; `onScreen` is the higher-contrast dark chip for placing over\n// busy/photo/video surfaces. The icon is `aria-hidden` and the root carries\n// `role=\"status\"` so the (visible or, when `hasLabel` is false, only\n// `aria-label`'d) text is the single accessible announcement — avoids double\n// announcement against `Spinner`'s own built-in status role.\nconst loadingVariants = cva('inline-flex items-center', {\n variants: {\n variant: {\n inline: 'gap-[var(--ui-loading-inline-container-gap)]',\n onSurfacePrimary:\n 'flex-col justify-center gap-[var(--ui-loading-element-container-gap)] rounded-lg bg-[var(--ui-loading-element-container-color-primary)] px-[var(--ui-loading-element-container-padding-x)] py-[var(--ui-loading-element-container-padding-y)]',\n onSurfaceSecondary:\n 'flex-col justify-center gap-[var(--ui-loading-element-container-gap)] rounded-lg bg-[var(--ui-loading-element-container-color-secondary)] px-[var(--ui-loading-element-container-padding-x)] py-[var(--ui-loading-element-container-padding-y)]',\n onScreen:\n 'flex-col justify-center gap-[var(--ui-loading-screen-container-gap)] rounded-lg bg-[var(--ui-loading-screen-container-color)] px-[var(--ui-loading-screen-container-padding-x)] py-[var(--ui-loading-screen-container-padding-y)]',\n },\n },\n defaultVariants: {\n variant: 'inline',\n },\n});\n\nconst spinnerSizeByVariant = {\n inline: 'sm',\n onSurfacePrimary: 'lg',\n onSurfaceSecondary: 'lg',\n onScreen: 'xl',\n} as const;\n\nconst iconColorClassByVariant: Record<string, string> = {\n inline: 'text-[var(--ui-loading-inline-icon-color)]',\n onSurfacePrimary: 'text-[var(--ui-loading-element-icon-color)]',\n onSurfaceSecondary: 'text-[var(--ui-loading-element-icon-color)]',\n onScreen: 'text-[var(--ui-loading-screen-icon-color)]',\n};\n\nconst labelClassByVariant: Record<string, string> = {\n inline: 'text-[var(--ui-loading-inline-label-color)]',\n onSurfacePrimary: 'text-[var(--ui-loading-element-label-color)]',\n onSurfaceSecondary: 'text-[var(--ui-loading-element-label-color)]',\n onScreen: 'text-[var(--ui-loading-screen-label-color)]',\n};\n\nexport interface LoadingProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof loadingVariants> {\n /** Whether the label is rendered. When `false`, `label` is still exposed to assistive tech via `aria-label`. */\n hasLabel?: boolean;\n /** The loading message. */\n label?: string;\n}\n\nconst Loading = React.forwardRef<HTMLDivElement, LoadingProps>(\n (\n {\n className,\n variant = 'inline',\n hasLabel = true,\n label = 'Data is loading…',\n ...props\n },\n ref\n ) => {\n const resolvedVariant = variant ?? 'inline';\n return (\n <div\n ref={ref}\n role=\"status\"\n aria-label={hasLabel ? undefined : label}\n className={cn(loadingVariants({ variant: resolvedVariant }), className)}\n {...props}\n >\n <Spinner\n aria-hidden=\"true\"\n size={spinnerSizeByVariant[resolvedVariant]}\n className={cn('shrink-0', iconColorClassByVariant[resolvedVariant])}\n />\n {hasLabel && (\n <span\n className={cn(\n 'whitespace-nowrap text-sm font-normal leading-6',\n labelClassByVariant[resolvedVariant]\n )}\n >\n {label}\n </span>\n )}\n </div>\n );\n }\n);\nLoading.displayName = 'Loading';\n\nexport { Loading, loadingVariants };\n"],"names":["loadingVariants","cva","spinnerSizeByVariant","iconColorClassByVariant","labelClassByVariant","Loading","React","className","variant","hasLabel","label","props","ref","resolvedVariant","jsxs","cn","jsx","Spinner"],"mappings":";;;;;AAkBA,MAAMA,IAAkBC,EAAI,4BAA4B;AAAA,EACtD,UAAU;AAAA,IACR,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,kBACE;AAAA,MACF,oBACE;AAAA,MACF,UACE;AAAA,IAAA;AAAA,EACJ;AAAA,EAEF,iBAAiB;AAAA,IACf,SAAS;AAAA,EAAA;AAEb,CAAC,GAEKC,IAAuB;AAAA,EAC3B,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,UAAU;AACZ,GAEMC,IAAkD;AAAA,EACtD,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,UAAU;AACZ,GAEMC,IAA8C;AAAA,EAClD,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,UAAU;AACZ,GAYMC,IAAUC,EAAM;AAAA,EACpB,CACE;AAAA,IACE,WAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,UAAAC,IAAW;AAAA,IACX,OAAAC,IAAQ;AAAA,IACR,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAMC,IAAkBL,KAAW;AACnC,WACE,gBAAAM;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAF;AAAA,QACA,MAAK;AAAA,QACL,cAAYH,IAAW,SAAYC;AAAA,QACnC,WAAWK,EAAGf,EAAgB,EAAE,SAASa,EAAA,CAAiB,GAAGN,CAAS;AAAA,QACrE,GAAGI;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAK;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,MAAMf,EAAqBW,CAAe;AAAA,cAC1C,WAAWE,EAAG,YAAYZ,EAAwBU,CAAe,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,UAEnEJ,KACC,gBAAAO;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD;AAAA,gBACT;AAAA,gBACAX,EAAoBS,CAAe;AAAA,cAAA;AAAA,cAGpC,UAAAH;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AACAL,EAAQ,cAAc;"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsxs as n, jsx as e, Fragment as x } from "react/jsx-runtime";
|
|
2
|
+
import * as p from "react";
|
|
3
|
+
import { Meter as t } from "@base-ui/react/meter";
|
|
4
|
+
import { cn as g } from "../../../lib/utils.js";
|
|
5
|
+
import { Tooltip as k, TooltipTrigger as M, TooltipContent as w } from "../tooltip/tooltip.js";
|
|
6
|
+
const y = (a) => a.toLocaleString(), T = p.forwardRef(
|
|
7
|
+
({
|
|
8
|
+
className: a,
|
|
9
|
+
label: l,
|
|
10
|
+
value: o,
|
|
11
|
+
max: r = 100,
|
|
12
|
+
color: c,
|
|
13
|
+
valueFormatter: s = y,
|
|
14
|
+
showTooltip: i = !0,
|
|
15
|
+
tooltip: f,
|
|
16
|
+
defaultOpen: h,
|
|
17
|
+
...b
|
|
18
|
+
}, m) => {
|
|
19
|
+
const d = r > 0 ? Math.round(o / r * 100) : 0, N = r > 0 ? r : 1, u = /* @__PURE__ */ n(
|
|
20
|
+
t.Root,
|
|
21
|
+
{
|
|
22
|
+
value: o,
|
|
23
|
+
max: N,
|
|
24
|
+
"aria-valuemax": r,
|
|
25
|
+
"aria-valuetext": `${s(o)} of ${s(r)} (${d}%)`,
|
|
26
|
+
tabIndex: i ? 0 : void 0,
|
|
27
|
+
className: g("flex w-full flex-col gap-1.5", a),
|
|
28
|
+
...b,
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ n("div", { className: "flex items-baseline justify-between gap-2 text-sm leading-none", children: [
|
|
31
|
+
/* @__PURE__ */ e(t.Label, { className: "truncate text-muted-foreground", children: l }),
|
|
32
|
+
/* @__PURE__ */ n("span", { className: "shrink-0 tabular-nums", children: [
|
|
33
|
+
/* @__PURE__ */ e("span", { className: "font-semibold text-foreground", children: s(o) }),
|
|
34
|
+
/* @__PURE__ */ n("span", { className: "text-muted-foreground", children: [
|
|
35
|
+
" · ",
|
|
36
|
+
d,
|
|
37
|
+
"%"
|
|
38
|
+
] })
|
|
39
|
+
] })
|
|
40
|
+
] }),
|
|
41
|
+
/* @__PURE__ */ e(t.Track, { className: "h-2 w-full overflow-hidden rounded-full bg-input", children: /* @__PURE__ */ e(
|
|
42
|
+
t.Indicator,
|
|
43
|
+
{
|
|
44
|
+
className: "rounded-full",
|
|
45
|
+
style: { backgroundColor: c }
|
|
46
|
+
}
|
|
47
|
+
) })
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
return i ? /* @__PURE__ */ n(k, { defaultOpen: h, children: [
|
|
52
|
+
/* @__PURE__ */ e(
|
|
53
|
+
M,
|
|
54
|
+
{
|
|
55
|
+
ref: m,
|
|
56
|
+
render: u
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ e(
|
|
60
|
+
w,
|
|
61
|
+
{
|
|
62
|
+
className: g(
|
|
63
|
+
"border border-border bg-background text-foreground shadow-md",
|
|
64
|
+
!f && "flex items-center gap-2"
|
|
65
|
+
),
|
|
66
|
+
children: f ?? /* @__PURE__ */ n(x, { children: [
|
|
67
|
+
/* @__PURE__ */ e(
|
|
68
|
+
"span",
|
|
69
|
+
{
|
|
70
|
+
className: "size-2.5 shrink-0 rounded-full",
|
|
71
|
+
style: { backgroundColor: c }
|
|
72
|
+
}
|
|
73
|
+
),
|
|
74
|
+
/* @__PURE__ */ e("span", { className: "font-semibold", children: l }),
|
|
75
|
+
/* @__PURE__ */ n("span", { className: "text-muted-foreground", children: [
|
|
76
|
+
s(o),
|
|
77
|
+
" of ",
|
|
78
|
+
s(r),
|
|
79
|
+
" · ",
|
|
80
|
+
d,
|
|
81
|
+
"%"
|
|
82
|
+
] })
|
|
83
|
+
] })
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
] }) : p.cloneElement(u, { ref: m });
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
T.displayName = "Meter";
|
|
90
|
+
export {
|
|
91
|
+
T as Meter
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=meter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meter.js","sources":["../../../../src/components/ui/meter/meter.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Meter as MeterPrimitive } from '@base-ui/react/meter';\n\nimport { cn } from '@/lib/utils';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';\n\n// A meter: a labelled bar showing a scalar value within a known range (a\n// fractional value / share), as opposed to `Progress` which tracks a task over\n// time — hence Base UI's Meter primitive (`role=\"meter\"`, mirroring the HTML\n// `<meter>` element). One row — label + `value · %` over a proportional track\n// bar — designed to be stacked into a ranked breakdown (a \"bar list\"). No new\n// tokens: the track reuses the shared `bg-input`, and the fill color is\n// caller-supplied per row (an existing `--ui-*` token); there is no chart\n// palette tier yet.\n\nconst defaultFormat = (value: number) => value.toLocaleString();\n\nexport interface MeterProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof MeterPrimitive.Root>,\n 'value' | 'color'\n > {\n /** Row label shown on the left. */\n label: string;\n /** The value this meter represents. */\n value: number;\n /** Upper bound of the range — the whole the value is a share of. */\n max?: number;\n /** Fill color for the bar — an existing semantic `--ui-*` token (or any CSS color). */\n color: string;\n /** Format the numeric value (label + tooltip). Defaults to `toLocaleString()`. */\n valueFormatter?: (value: number) => string;\n /** Show the hover tooltip (`label · value of max · %`). */\n showTooltip?: boolean;\n /**\n * Custom tooltip content — replaces the default (dot + label + `value of max\n * · %`) inside the same chart-style card. Ignored when `showTooltip` is false.\n */\n tooltip?: React.ReactNode;\n /** Render with the tooltip initially open (Base UI `defaultOpen`). */\n defaultOpen?: boolean;\n}\n\nconst Meter = React.forwardRef<HTMLDivElement, MeterProps>(\n (\n {\n className,\n label,\n value,\n max = 100,\n color,\n valueFormatter = defaultFormat,\n showTooltip = true,\n tooltip,\n defaultOpen,\n ...props\n },\n ref\n ) => {\n const pct = max > 0 ? Math.round((value / max) * 100) : 0;\n // Base UI derives the indicator width from value/max; a non-positive max\n // would divide by zero and leave the fill unspecified, so floor it at 1\n // (value is 0 for a degenerate row → a 0% fill that matches `pct`).\n const safeMax = max > 0 ? max : 1;\n\n const root = (\n <MeterPrimitive.Root\n value={value}\n max={safeMax}\n // Base UI derives aria-valuemax from the (clamped) max prop; override it\n // back to the real max so the numeric ARIA triad agrees with the\n // aria-valuetext / visible text on a degenerate max<=0 row.\n aria-valuemax={max}\n aria-valuetext={`${valueFormatter(value)} of ${valueFormatter(max)} (${pct}%)`}\n // When wrapped in a Tooltip the meter div is the trigger; make it\n // focusable so keyboard users can open the tooltip (hover-only\n // otherwise). Without a tooltip there's nothing to reveal on focus.\n tabIndex={showTooltip ? 0 : undefined}\n className={cn('flex w-full flex-col gap-1.5', className)}\n {...props}\n >\n <div className=\"flex items-baseline justify-between gap-2 text-sm leading-none\">\n <MeterPrimitive.Label className=\"truncate text-muted-foreground\">\n {label}\n </MeterPrimitive.Label>\n <span className=\"shrink-0 tabular-nums\">\n <span className=\"font-semibold text-foreground\">\n {valueFormatter(value)}\n </span>\n <span className=\"text-muted-foreground\"> · {pct}%</span>\n </span>\n </div>\n <MeterPrimitive.Track className=\"h-2 w-full overflow-hidden rounded-full bg-input\">\n {/* Base UI sizes the indicator from value/max; we only theme it. */}\n <MeterPrimitive.Indicator\n className=\"rounded-full\"\n style={{ backgroundColor: color }}\n />\n </MeterPrimitive.Track>\n </MeterPrimitive.Root>\n );\n\n if (!showTooltip) {\n return React.cloneElement(root, { ref });\n }\n\n return (\n <Tooltip defaultOpen={defaultOpen}>\n <TooltipTrigger\n // Base UI's Trigger ref is typed to its default <button>; the trigger\n // is the meter root (a div), so the runtime ref is that div.\n ref={ref as React.Ref<HTMLButtonElement>}\n render={root}\n />\n {/* Match the chart tooltip look (light card: border + surface + shadow),\n not the default dark bubble — this is a data-viz widget. The consumer\n can replace the inner content via `tooltip`. */}\n <TooltipContent\n className={cn(\n 'border border-border bg-background text-foreground shadow-md',\n !tooltip && 'flex items-center gap-2'\n )}\n >\n {tooltip ?? (\n <>\n <span\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: color }}\n />\n <span className=\"font-semibold\">{label}</span>\n <span className=\"text-muted-foreground\">\n {valueFormatter(value)} of {valueFormatter(max)} · {pct}%\n </span>\n </>\n )}\n </TooltipContent>\n </Tooltip>\n );\n }\n);\nMeter.displayName = 'Meter';\n\nexport { Meter };\n"],"names":["defaultFormat","value","Meter","React","className","label","max","color","valueFormatter","showTooltip","tooltip","defaultOpen","props","ref","pct","safeMax","root","jsxs","MeterPrimitive","cn","jsx","Tooltip","TooltipTrigger","TooltipContent","Fragment"],"mappings":";;;;;AAiBA,MAAMA,IAAgB,CAACC,MAAkBA,EAAM,eAAA,GA4BzCC,IAAQC,EAAM;AAAA,EAClB,CACE;AAAA,IACE,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,OAAAJ;AAAA,IACA,KAAAK,IAAM;AAAA,IACN,OAAAC;AAAA,IACA,gBAAAC,IAAiBR;AAAA,IACjB,aAAAS,IAAc;AAAA,IACd,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAMC,IAAMR,IAAM,IAAI,KAAK,MAAOL,IAAQK,IAAO,GAAG,IAAI,GAIlDS,IAAUT,IAAM,IAAIA,IAAM,GAE1BU,IACJ,gBAAAC;AAAA,MAACC,EAAe;AAAA,MAAf;AAAA,QACC,OAAAjB;AAAA,QACA,KAAKc;AAAA,QAIL,iBAAeT;AAAA,QACf,kBAAgB,GAAGE,EAAeP,CAAK,CAAC,OAAOO,EAAeF,CAAG,CAAC,KAAKQ,CAAG;AAAA,QAI1E,UAAUL,IAAc,IAAI;AAAA,QAC5B,WAAWU,EAAG,gCAAgCf,CAAS;AAAA,QACtD,GAAGQ;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAK,EAAC,OAAA,EAAI,WAAU,kEACb,UAAA;AAAA,YAAA,gBAAAG,EAACF,EAAe,OAAf,EAAqB,WAAU,kCAC7B,UAAAb,GACH;AAAA,YACA,gBAAAY,EAAC,QAAA,EAAK,WAAU,yBACd,UAAA;AAAA,cAAA,gBAAAG,EAAC,QAAA,EAAK,WAAU,iCACb,UAAAZ,EAAeP,CAAK,GACvB;AAAA,cACA,gBAAAgB,EAAC,QAAA,EAAK,WAAU,yBAAwB,UAAA;AAAA,gBAAA;AAAA,gBAAIH;AAAA,gBAAI;AAAA,cAAA,EAAA,CAAC;AAAA,YAAA,EAAA,CACnD;AAAA,UAAA,GACF;AAAA,UACA,gBAAAM,EAACF,EAAe,OAAf,EAAqB,WAAU,oDAE9B,UAAA,gBAAAE;AAAA,YAACF,EAAe;AAAA,YAAf;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,iBAAiBX,EAAA;AAAA,YAAM;AAAA,UAAA,EAClC,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAIJ,WAAKE,IAKH,gBAAAQ,EAACI,KAAQ,aAAAV,GACP,UAAA;AAAA,MAAA,gBAAAS;AAAA,QAACE;AAAA,QAAA;AAAA,UAGC,KAAAT;AAAA,UACA,QAAQG;AAAA,QAAA;AAAA,MAAA;AAAA,MAKV,gBAAAI;AAAA,QAACG;AAAA,QAAA;AAAA,UACC,WAAWJ;AAAA,YACT;AAAA,YACA,CAACT,KAAW;AAAA,UAAA;AAAA,UAGb,eACC,gBAAAO,EAAAO,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAJ;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiBb,EAAA;AAAA,cAAM;AAAA,YAAA;AAAA,YAElC,gBAAAa,EAAC,QAAA,EAAK,WAAU,iBAAiB,UAAAf,GAAM;AAAA,YACvC,gBAAAY,EAAC,QAAA,EAAK,WAAU,yBACb,UAAA;AAAA,cAAAT,EAAeP,CAAK;AAAA,cAAE;AAAA,cAAKO,EAAeF,CAAG;AAAA,cAAE;AAAA,cAAIQ;AAAA,cAAI;AAAA,YAAA,EAAA,CAC1D;AAAA,UAAA,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAEJ,GACF,IAjCOX,EAAM,aAAaa,GAAM,EAAE,KAAAH,GAAK;AAAA,EAmC3C;AACF;AACAX,EAAM,cAAc;"}
|