@mittwald/flow-react-components 1.5.0-next.45 → 1.5.0-next.47
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/assets/component-index.json +1 -1
- package/dist/assets/doc-properties.json +1 -1
- package/dist/css/all-layered.css +1 -1
- package/dist/css/all.css +1 -1
- package/dist/js/packages/components/src/components/Calendar/Calendar.mjs +7 -4
- package/dist/js/packages/components/src/components/Calendar/Calendar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Calendar/Calendar.module.mjs +6 -2
- package/dist/js/packages/components/src/components/Calendar/Calendar.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Calendar/components/RangeCalendar/RangeCalendar.mjs +5 -2
- package/dist/js/packages/components/src/components/Calendar/components/RangeCalendar/RangeCalendar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.mjs +11 -0
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.module.mjs +6 -2
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CodeBlock/CodeBlock.mjs +8 -4
- package/dist/js/packages/components/src/components/CodeBlock/CodeBlock.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CodeBlock/CodeBlock.module.mjs +6 -2
- package/dist/js/packages/components/src/components/CodeBlock/CodeBlock.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.mjs +42 -30
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.module.mjs +8 -2
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DonutChart/DonutChart.mjs +30 -16
- package/dist/js/packages/components/src/components/DonutChart/DonutChart.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DonutChart/DonutChart.module.mjs +6 -2
- package/dist/js/packages/components/src/components/DonutChart/DonutChart.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DonutChart/components/Donut.mjs +5 -2
- package/dist/js/packages/components/src/components/DonutChart/components/Donut.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileDropZone/FileDropZone.mjs +6 -3
- package/dist/js/packages/components/src/components/FileDropZone/FileDropZone.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileDropZone/FileDropZone.module.mjs +6 -2
- package/dist/js/packages/components/src/components/FileDropZone/FileDropZone.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ImageCropper/ImageCropper.mjs +27 -22
- package/dist/js/packages/components/src/components/ImageCropper/ImageCropper.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ImageCropper/ImageCropper.module.mjs +6 -2
- package/dist/js/packages/components/src/components/ImageCropper/ImageCropper.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Kbd/Kbd.mjs +4 -1
- package/dist/js/packages/components/src/components/Kbd/Kbd.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Kbd/Kbd.module.mjs +6 -2
- package/dist/js/packages/components/src/components/Kbd/Kbd.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Markdown/Markdown.mjs +19 -3
- package/dist/js/packages/components/src/components/Markdown/Markdown.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Markdown/Markdown.module.mjs +6 -2
- package/dist/js/packages/components/src/components/Markdown/Markdown.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Markdown/components/SkeletonBlocks.mjs +82 -0
- package/dist/js/packages/components/src/components/Markdown/components/SkeletonBlocks.mjs.map +1 -0
- package/dist/js/packages/components/src/components/MarkdownEditor/MarkdownEditor.mjs +9 -6
- package/dist/js/packages/components/src/components/MarkdownEditor/MarkdownEditor.mjs.map +1 -1
- package/dist/js/packages/components/src/components/MarkdownEditor/MarkdownEditor.module.mjs +8 -2
- package/dist/js/packages/components/src/components/MarkdownEditor/MarkdownEditor.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Modal/Modal.module.mjs +2 -0
- package/dist/js/packages/components/src/components/Modal/Modal.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/SkeletonMode/components/SkeletonTextContent/SkeletonTextContent.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableCell/TableCell.mjs +2 -1
- package/dist/js/packages/components/src/components/Table/components/TableCell/TableCell.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableColumn/TableColumn.mjs +2 -1
- package/dist/js/packages/components/src/components/Table/components/TableColumn/TableColumn.mjs.map +1 -1
- package/dist/js/packages/components/src/integrations/react-hook-form/components/Field/Field.mjs +1 -2
- package/dist/js/packages/components/src/integrations/react-hook-form/components/Field/Field.mjs.map +1 -1
- package/dist/types/components/DonutChart/components/Donut.d.ts +2 -0
- package/dist/types/components/Markdown/components/SkeletonBlocks.d.ts +15 -0
- package/package.json +9 -9
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
/* */
|
|
3
|
+
import { useSkeletonMode } from "../SkeletonMode/skeletonModeContext.mjs";
|
|
3
4
|
import { Wrap } from "../Wrap/Wrap.mjs";
|
|
4
5
|
import DonutChart_module_default from "./DonutChart.module.mjs";
|
|
5
6
|
import { DonutChartValue } from "./components/DonutChartValue.mjs";
|
|
6
|
-
import { Donut } from "./components/Donut.mjs";
|
|
7
|
+
import { Donut, getDonutSize } from "./components/Donut.mjs";
|
|
7
8
|
import { DonutChartLegend } from "./components/DonutChartLegend.mjs";
|
|
8
9
|
import clsx from "clsx";
|
|
9
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -14,25 +15,38 @@ var DonutChart = (props) => {
|
|
|
14
15
|
const { size = "m", status = "info", className, value, segments, maxValue, formatOptions, showLegend = true, legendPosition = "right", children, ...rest } = props;
|
|
15
16
|
const rootClassName = clsx(DonutChart_module_default.donutChart, size === "l" && DonutChart_module_default["size-l"], DonutChart_module_default[status], className);
|
|
16
17
|
const segmentsTotalValue = segments ? segments.map((s) => s.value).reduce((a, b) => a + b, 0) : void 0;
|
|
18
|
+
const isSkeleton = useSkeletonMode();
|
|
19
|
+
const donutSize = getDonutSize(size);
|
|
20
|
+
const displayedValue = segmentsTotalValue ?? value;
|
|
21
|
+
const skeletonDonut = /* @__PURE__ */ jsx("span", {
|
|
22
|
+
className: clsx(DonutChart_module_default.donutChart, DonutChart_module_default.skeleton, className),
|
|
23
|
+
style: {
|
|
24
|
+
width: donutSize,
|
|
25
|
+
height: donutSize
|
|
26
|
+
},
|
|
27
|
+
"aria-hidden": true,
|
|
28
|
+
inert: true
|
|
29
|
+
});
|
|
30
|
+
const donut = /* @__PURE__ */ jsxs(Aria.ProgressBar, {
|
|
31
|
+
className: rootClassName,
|
|
32
|
+
value: displayedValue,
|
|
33
|
+
...rest,
|
|
34
|
+
children: [/* @__PURE__ */ jsx(Donut, {
|
|
35
|
+
value: displayedValue,
|
|
36
|
+
segments,
|
|
37
|
+
size,
|
|
38
|
+
maxValue
|
|
39
|
+
}), /* @__PURE__ */ jsx(DonutChartValue, {
|
|
40
|
+
value: displayedValue,
|
|
41
|
+
formatOptions,
|
|
42
|
+
children
|
|
43
|
+
})]
|
|
44
|
+
});
|
|
17
45
|
return /* @__PURE__ */ jsx(Wrap, {
|
|
18
46
|
if: showLegend && segments,
|
|
19
47
|
children: /* @__PURE__ */ jsxs("div", {
|
|
20
48
|
className: clsx(DonutChart_module_default.donutChartContainer, DonutChart_module_default[legendPosition]),
|
|
21
|
-
children: [/* @__PURE__ */
|
|
22
|
-
className: rootClassName,
|
|
23
|
-
value: segmentsTotalValue ?? value,
|
|
24
|
-
...rest,
|
|
25
|
-
children: [/* @__PURE__ */ jsx(Donut, {
|
|
26
|
-
value: segmentsTotalValue ?? value,
|
|
27
|
-
segments,
|
|
28
|
-
size,
|
|
29
|
-
maxValue
|
|
30
|
-
}), /* @__PURE__ */ jsx(DonutChartValue, {
|
|
31
|
-
value: segmentsTotalValue ?? value,
|
|
32
|
-
formatOptions,
|
|
33
|
-
children
|
|
34
|
-
})]
|
|
35
|
-
}), showLegend && segments && /* @__PURE__ */ jsx(DonutChartLegend, {
|
|
49
|
+
children: [isSkeleton ? skeletonDonut : donut, showLegend && segments && /* @__PURE__ */ jsx(DonutChartLegend, {
|
|
36
50
|
showLegend,
|
|
37
51
|
segments,
|
|
38
52
|
formatOptions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DonutChart.mjs","names":["styles"],"sources":["../../../../../../../src/components/DonutChart/DonutChart.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport styles from \"./DonutChart.module.scss\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { DonutChartValue } from \"@/components/DonutChart/components/DonutChartValue\";\nimport { Donut } from \"@/components/DonutChart/components/Donut\";\nimport { Wrap } from \"@/components/Wrap\";\nimport { DonutChartLegend } from \"@/components/DonutChart/components/DonutChartLegend\";\nimport type { Status } from \"@/lib/types/props\";\n\nexport interface DonutChartSegment {\n value: number;\n title: string;\n color?: CategoricalWithCustomColor;\n valueText?: string;\n}\n\nexport interface DonutChartProps\n extends\n Omit<Aria.ProgressBarProps, \"children\" | \"valueLabel\">,\n PropsWithChildren {\n /** The status the donut chart is colored by. */\n status?: Exclude<Status, \"unavailable\">;\n /** The size variant of the donut chart. @default \"m\" */\n size?: \"m\" | \"l\";\n /** Divides the fill of the donut chart into segments */\n segments?: DonutChartSegment[];\n /**\n * Whether the legend component is shown when segments are used. @default:\n * true\n */\n showLegend?: boolean;\n /** The position of the legend. @default \"right\" */\n legendPosition?: \"top\" | \"left\" | \"bottom\" | \"right\";\n}\n\n/** @flr-generate all */\nexport const DonutChart: FC<DonutChartProps> = (props) => {\n const {\n size = \"m\",\n status = \"info\",\n className,\n value,\n segments,\n maxValue,\n formatOptions,\n showLegend = true,\n legendPosition = \"right\",\n children,\n ...rest\n } = props;\n\n const rootClassName = clsx(\n styles.donutChart,\n size === \"l\" && styles[\"size-l\"],\n styles[status],\n className,\n );\n\n const segmentsTotalValue = segments\n ? segments.map((s) => s.value).reduce((a, b) => a + b, 0)\n : undefined;\n\n
|
|
1
|
+
{"version":3,"file":"DonutChart.mjs","names":["styles"],"sources":["../../../../../../../src/components/DonutChart/DonutChart.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport styles from \"./DonutChart.module.scss\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { DonutChartValue } from \"@/components/DonutChart/components/DonutChartValue\";\nimport { Donut, getDonutSize } from \"@/components/DonutChart/components/Donut\";\nimport { Wrap } from \"@/components/Wrap\";\nimport { DonutChartLegend } from \"@/components/DonutChart/components/DonutChartLegend\";\nimport type { Status } from \"@/lib/types/props\";\nimport { useSkeletonMode } from \"@/components/SkeletonMode/skeletonModeContext\";\n\nexport interface DonutChartSegment {\n value: number;\n title: string;\n color?: CategoricalWithCustomColor;\n valueText?: string;\n}\n\nexport interface DonutChartProps\n extends\n Omit<Aria.ProgressBarProps, \"children\" | \"valueLabel\">,\n PropsWithChildren {\n /** The status the donut chart is colored by. */\n status?: Exclude<Status, \"unavailable\">;\n /** The size variant of the donut chart. @default \"m\" */\n size?: \"m\" | \"l\";\n /** Divides the fill of the donut chart into segments */\n segments?: DonutChartSegment[];\n /**\n * Whether the legend component is shown when segments are used. @default:\n * true\n */\n showLegend?: boolean;\n /** The position of the legend. @default \"right\" */\n legendPosition?: \"top\" | \"left\" | \"bottom\" | \"right\";\n}\n\n/** @flr-generate all */\nexport const DonutChart: FC<DonutChartProps> = (props) => {\n const {\n size = \"m\",\n status = \"info\",\n className,\n value,\n segments,\n maxValue,\n formatOptions,\n showLegend = true,\n legendPosition = \"right\",\n children,\n ...rest\n } = props;\n\n const rootClassName = clsx(\n styles.donutChart,\n size === \"l\" && styles[\"size-l\"],\n styles[status],\n className,\n );\n\n const segmentsTotalValue = segments\n ? segments.map((s) => s.value).reduce((a, b) => a + b, 0)\n : undefined;\n\n const isSkeleton = useSkeletonMode();\n const donutSize = getDonutSize(size);\n\n const displayedValue = segmentsTotalValue ?? value;\n\n /* No svg: the donut is one round surface in its size. The legend follows\n the skeleton rules of its items. */\n const skeletonDonut = (\n <span\n className={clsx(styles.donutChart, styles.skeleton, className)}\n style={{ width: donutSize, height: donutSize }}\n aria-hidden\n inert\n />\n );\n\n const donut = (\n <Aria.ProgressBar\n className={rootClassName}\n value={displayedValue}\n {...rest}\n >\n <Donut\n value={displayedValue}\n segments={segments}\n size={size}\n maxValue={maxValue}\n />\n <DonutChartValue value={displayedValue} formatOptions={formatOptions}>\n {children}\n </DonutChartValue>\n </Aria.ProgressBar>\n );\n\n return (\n <Wrap if={showLegend && segments}>\n <div className={clsx(styles.donutChartContainer, styles[legendPosition])}>\n {isSkeleton ? skeletonDonut : donut}\n\n {showLegend && segments && (\n <DonutChartLegend\n showLegend={showLegend}\n segments={segments}\n formatOptions={formatOptions}\n />\n )}\n </div>\n </Wrap>\n );\n};\n\nexport default DonutChart;\n"],"mappings":";;;;;;;;;;;;;AAuCA,IAAa,cAAmC,UAAU;CACxD,MAAM,EACJ,OAAO,KACP,SAAS,QACT,WACA,OACA,UACA,UACA,eACA,aAAa,MACb,iBAAiB,SACjB,UACA,GAAG,SACD;CAEJ,MAAM,gBAAgB,KACpBA,0BAAO,YACP,SAAS,OAAOA,0BAAO,WACvBA,0BAAO,SACP,SACF;CAEA,MAAM,qBAAqB,WACvB,SAAS,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IACtD,KAAA;CAEJ,MAAM,aAAa,gBAAgB;CACnC,MAAM,YAAY,aAAa,IAAI;CAEnC,MAAM,iBAAiB,sBAAsB;CAI7C,MAAM,gBACJ,oBAAC,QAAD;EACE,WAAW,KAAKA,0BAAO,YAAYA,0BAAO,UAAU,SAAS;EAC7D,OAAO;GAAE,OAAO;GAAW,QAAQ;EAAU;EAC7C,eAAA;EACA,OAAA;CACD,CAAA;CAGH,MAAM,QACJ,qBAAC,KAAK,aAAN;EACE,WAAW;EACX,OAAO;EACP,GAAI;EAHN,UAAA,CAKE,oBAAC,OAAD;GACE,OAAO;GACG;GACJ;GACI;EACX,CAAA,GACD,oBAAC,iBAAD;GAAiB,OAAO;GAA+B;GACpD;EACc,CAAA,CACD;;CAGpB,OACE,oBAAC,MAAD;EAAM,IAAI,cAAc;EACtB,UAAA,qBAAC,OAAD;GAAK,WAAW,KAAKA,0BAAO,qBAAqBA,0BAAO,eAAe;GAAvE,UAAA,CACG,aAAa,gBAAgB,OAE7B,cAAc,YACb,oBAAC,kBAAD;IACc;IACF;IACK;GAChB,CAAA,CAEA;;CACD,CAAA;AAEV"}
|
|
@@ -11,6 +11,7 @@ var info = "flow--donut-chart--info";
|
|
|
11
11
|
var success = "flow--donut-chart--success";
|
|
12
12
|
var danger = "flow--donut-chart--danger";
|
|
13
13
|
var warning = "flow--donut-chart--warning";
|
|
14
|
+
var skeleton = "flow--donut-chart--skeleton";
|
|
14
15
|
var donutChartContainer = "flow--donut-chart--donut-chart-container";
|
|
15
16
|
var bottom = "flow--donut-chart--bottom";
|
|
16
17
|
var top = "flow--donut-chart--top";
|
|
@@ -30,14 +31,17 @@ var DonutChart_module_default = {
|
|
|
30
31
|
success,
|
|
31
32
|
danger,
|
|
32
33
|
warning,
|
|
34
|
+
skeleton,
|
|
35
|
+
"skeleton-surface-shimmer": "flow--donut-chart--skeleton-surface-shimmer",
|
|
33
36
|
donutChartContainer,
|
|
34
37
|
bottom,
|
|
35
38
|
top,
|
|
36
39
|
right,
|
|
37
40
|
legend,
|
|
38
|
-
left
|
|
41
|
+
left,
|
|
42
|
+
"skeleton-text-shimmer": "flow--donut-chart--skeleton-text-shimmer"
|
|
39
43
|
};
|
|
40
44
|
//#endregion
|
|
41
|
-
export { background, border, bottom, danger, DonutChart_module_default as default, donutChart, donutChartContainer, fill, info, left, legend, right, segment, success, top, value, warning };
|
|
45
|
+
export { background, border, bottom, danger, DonutChart_module_default as default, donutChart, donutChartContainer, fill, info, left, legend, right, segment, skeleton, success, top, value, warning };
|
|
42
46
|
|
|
43
47
|
//# sourceMappingURL=DonutChart.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DonutChart.module.mjs","names":[],"sources":["../../../../../../../src/components/DonutChart/DonutChart.module.scss"],"sourcesContent":[".donutChart {\n position: relative;\n width: fit-content;\n height: fit-content;\n flex-shrink: 0;\n\n .border {\n stroke: var(--donut-chart--border-color);\n }\n\n .background {\n stroke: var(--donut-chart--background-color);\n }\n\n .fill,\n .segment {\n /* No `calc()`: with a unitless one on the dash, Firefox drew full circles. */\n stroke-dasharray: var(--donut-chart--percent) 100;\n transform: rotate(calc(var(--donut-chart--offset) * 3.6deg - 90deg));\n transform-box: fill-box;\n transform-origin: center;\n animation: donut-chart-fill var(--donut-chart--transition-duration) ease;\n }\n\n .value {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow-wrap: anywhere;\n padding: var(--donut-chart--padding--m);\n }\n\n &.size-l {\n .value {\n font-size: var(--font-size-heading--xl);\n padding: var(--donut-chart--padding--l);\n\n // Raw consumer markup inside the value slot — nothing to class.\n // stylelint-disable-next-line selector-max-type -- consumer markup\n small {\n font-size: var(--font-size-heading--l);\n }\n }\n }\n\n /* Variants */\n @mixin status($status) {\n &.#{$status} {\n .fill {\n stroke: var(--donut-chart--#{$status}-fill-background-color);\n }\n }\n }\n\n @include status(info);\n @include status(success);\n @include status(danger);\n @include status(warning);\n}\n\n.donutChartContainer {\n display: flex;\n gap: var(--donut-chart--spacing-y) var(--donut-chart--spacing-x);\n align-items: center;\n\n &.bottom {\n flex-direction: column;\n }\n\n &.top {\n flex-direction: column-reverse;\n }\n\n &.right {\n .legend {\n justify-content: start;\n }\n }\n\n &.left {\n flex-direction: row-reverse;\n\n .legend {\n justify-content: start;\n }\n }\n}\n\n/* The implicit \"to\" keyframe picks up the fill's own dash and rotation. */\n@keyframes donut-chart-fill {\n from {\n stroke-dasharray: 0 100;\n transform: rotate(-90deg);\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"DonutChart.module.mjs","names":[],"sources":["../../../../../../../src/components/DonutChart/DonutChart.module.scss"],"sourcesContent":["@use \"@/styles/mixins/skeleton\";\n\n.donutChart {\n position: relative;\n width: fit-content;\n height: fit-content;\n flex-shrink: 0;\n\n .border {\n stroke: var(--donut-chart--border-color);\n }\n\n .background {\n stroke: var(--donut-chart--background-color);\n }\n\n .fill,\n .segment {\n /* No `calc()`: with a unitless one on the dash, Firefox drew full circles. */\n stroke-dasharray: var(--donut-chart--percent) 100;\n transform: rotate(calc(var(--donut-chart--offset) * 3.6deg - 90deg));\n transform-box: fill-box;\n transform-origin: center;\n animation: donut-chart-fill var(--donut-chart--transition-duration) ease;\n }\n\n .value {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow-wrap: anywhere;\n padding: var(--donut-chart--padding--m);\n }\n\n &.size-l {\n .value {\n font-size: var(--font-size-heading--xl);\n padding: var(--donut-chart--padding--l);\n\n // Raw consumer markup inside the value slot — nothing to class.\n // stylelint-disable-next-line selector-max-type -- consumer markup\n small {\n font-size: var(--font-size-heading--l);\n }\n }\n }\n\n /* Variants */\n @mixin status($status) {\n &.#{$status} {\n .fill {\n stroke: var(--donut-chart--#{$status}-fill-background-color);\n }\n }\n }\n\n @include status(info);\n @include status(success);\n @include status(danger);\n @include status(warning);\n\n /* SkeletonMode */\n\n &.skeleton {\n @include skeleton.surface;\n\n --skeleton-radius: var(--corner-radius--round);\n\n display: block;\n }\n}\n\n@include skeleton.keyframes;\n\n.donutChartContainer {\n display: flex;\n gap: var(--donut-chart--spacing-y) var(--donut-chart--spacing-x);\n align-items: center;\n\n &.bottom {\n flex-direction: column;\n }\n\n &.top {\n flex-direction: column-reverse;\n }\n\n &.right {\n .legend {\n justify-content: start;\n }\n }\n\n &.left {\n flex-direction: row-reverse;\n\n .legend {\n justify-content: start;\n }\n }\n}\n\n/* The implicit \"to\" keyframe picks up the fill's own dash and rotation. */\n@keyframes donut-chart-fill {\n from {\n stroke-dasharray: 0 100;\n transform: rotate(-90deg);\n }\n}\n"],"mappings":""}
|
|
@@ -4,10 +4,13 @@ import DonutChart_module_default from "../DonutChart.module.mjs";
|
|
|
4
4
|
import { DonutChartFill } from "./DonutChartFill.mjs";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/DonutChart/components/Donut.tsx
|
|
7
|
+
var getFillWidth = (size) => size === "m" ? 8 : 12;
|
|
8
|
+
/** The width and height of the rendered donut in px. */
|
|
9
|
+
var getDonutSize = (size) => getFillWidth(size) * 16;
|
|
7
10
|
var Donut = (props) => {
|
|
8
11
|
const { value = 0, segments, size, maxValue: maxValueFromProps } = props;
|
|
9
12
|
const strokeWidth = .5;
|
|
10
|
-
const fillWidth = size
|
|
13
|
+
const fillWidth = getFillWidth(size);
|
|
11
14
|
const center = fillWidth * 4;
|
|
12
15
|
const radius = center - fillWidth / 2;
|
|
13
16
|
const maxValue = maxValueFromProps ?? 100;
|
|
@@ -50,6 +53,6 @@ var Donut = (props) => {
|
|
|
50
53
|
}) });
|
|
51
54
|
};
|
|
52
55
|
//#endregion
|
|
53
|
-
export { Donut };
|
|
56
|
+
export { Donut, getDonutSize };
|
|
54
57
|
|
|
55
58
|
//# sourceMappingURL=Donut.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Donut.mjs","names":["_Fragment","styles"],"sources":["../../../../../../../../src/components/DonutChart/components/Donut.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport styles from \"@/components/DonutChart/DonutChart.module.scss\";\nimport { DonutChartFill } from \"@/components/DonutChart/components/DonutChartFill\";\nimport type { DonutChartProps } from \"@/components/DonutChart\";\n\ninterface Props extends Pick<\n DonutChartProps,\n \"segments\" | \"size\" | \"maxValue\"\n> {\n value?: number;\n}\n\nexport const Donut: FC<Props> = (props) => {\n const { value = 0, segments, size, maxValue: maxValueFromProps } = props;\n\n const strokeWidth = 0.5;\n const fillWidth = size
|
|
1
|
+
{"version":3,"file":"Donut.mjs","names":["_Fragment","styles"],"sources":["../../../../../../../../src/components/DonutChart/components/Donut.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport styles from \"@/components/DonutChart/DonutChart.module.scss\";\nimport { DonutChartFill } from \"@/components/DonutChart/components/DonutChartFill\";\nimport type { DonutChartProps } from \"@/components/DonutChart\";\n\ninterface Props extends Pick<\n DonutChartProps,\n \"segments\" | \"size\" | \"maxValue\"\n> {\n value?: number;\n}\n\nconst getFillWidth = (size: DonutChartProps[\"size\"]) => (size === \"m\" ? 8 : 12);\n\n/** The width and height of the rendered donut in px. */\nexport const getDonutSize = (size: DonutChartProps[\"size\"]) =>\n getFillWidth(size) * 16;\n\nexport const Donut: FC<Props> = (props) => {\n const { value = 0, segments, size, maxValue: maxValueFromProps } = props;\n\n const strokeWidth = 0.5;\n const fillWidth = getFillWidth(size);\n const center = fillWidth * 4;\n const radius = center - fillWidth / 2;\n const maxValue = maxValueFromProps ?? 100;\n\n return (\n <>\n <svg\n width={center * 4}\n height={center * 4}\n viewBox={`0 0 ${center * 2} ${center * 2}`}\n fill=\"none\"\n strokeWidth={fillWidth}\n >\n <circle\n className={styles.background}\n cx={center}\n cy={center}\n r={radius}\n strokeWidth={fillWidth}\n />\n <circle\n className={styles.border}\n cx={center}\n cy={center}\n r={center - strokeWidth / 2}\n strokeWidth={strokeWidth}\n />\n <circle\n className={styles.border}\n cx={center}\n cy={center}\n r={center - fillWidth + strokeWidth / 2}\n strokeWidth={strokeWidth}\n />\n\n <DonutChartFill\n radius={radius}\n center={center}\n value={value < maxValue ? value : maxValue}\n segments={segments}\n maxValue={maxValue}\n />\n </svg>\n </>\n );\n};\n"],"mappings":";;;;;;AAYA,IAAM,gBAAgB,SAAmC,SAAS,MAAM,IAAI;;AAG5E,IAAa,gBAAgB,SAC3B,aAAa,IAAI,IAAI;AAEvB,IAAa,SAAoB,UAAU;CACzC,MAAM,EAAE,QAAQ,GAAG,UAAU,MAAM,UAAU,sBAAsB;CAEnE,MAAM,cAAc;CACpB,MAAM,YAAY,aAAa,IAAI;CACnC,MAAM,SAAS,YAAY;CAC3B,MAAM,SAAS,SAAS,YAAY;CACpC,MAAM,WAAW,qBAAqB;CAEtC,OACE,oBAAAA,UAAA,EAAA,UACE,qBAAC,OAAD;EACE,OAAO,SAAS;EAChB,QAAQ,SAAS;EACjB,SAAS,OAAO,SAAS,EAAE,GAAG,SAAS;EACvC,MAAK;EACL,aAAa;EALf,UAAA;GAOE,oBAAC,UAAD;IACE,WAAWC,0BAAO;IAClB,IAAI;IACJ,IAAI;IACJ,GAAG;IACH,aAAa;GACd,CAAA;GACD,oBAAC,UAAD;IACE,WAAWA,0BAAO;IAClB,IAAI;IACJ,IAAI;IACJ,GAAG,SAAS,cAAc;IACb;GACd,CAAA;GACD,oBAAC,UAAD;IACE,WAAWA,0BAAO;IAClB,IAAI;IACJ,IAAI;IACJ,GAAG,SAAS,YAAY,cAAc;IACzB;GACd,CAAA;GAED,oBAAC,gBAAD;IACU;IACA;IACR,OAAO,QAAQ,WAAW,QAAQ;IACxB;IACA;GACX,CAAA;EACE;CACL,CAAA,EAAA,CAAA;AAEN"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/* */
|
|
3
3
|
import { PropsContextProvider } from "../../lib/propsContext/components/PropsContextProvider.mjs";
|
|
4
4
|
import { flowComponent } from "../../lib/componentFactory/flowComponent.mjs";
|
|
5
|
+
import { SkeletonModeReset, useSkeletonMode } from "../SkeletonMode/skeletonModeContext.mjs";
|
|
5
6
|
import { useFieldComponent } from "../../lib/hooks/useFieldComponent.mjs";
|
|
6
7
|
import { IllustratedMessage } from "../IllustratedMessage/IllustratedMessage.mjs";
|
|
7
8
|
import FileDropZone_module_default from "./FileDropZone.module.mjs";
|
|
@@ -16,7 +17,8 @@ var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
|
16
17
|
const { multiple, accept, className, onChange: onChangeDropZone, children, name, isDisabled, isReadOnly } = props;
|
|
17
18
|
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext } = useFieldComponent(props, "FileDropZone");
|
|
18
19
|
const fileFieldRef = useRef(null);
|
|
19
|
-
const
|
|
20
|
+
const isSkeleton = useSkeletonMode();
|
|
21
|
+
const rootClassName = clsx(FileDropZone_module_default.fileDropZone, isDisabled && FileDropZone_module_default.disabled, isSkeleton && FileDropZone_module_default.skeleton, className);
|
|
20
22
|
const propsContext = {
|
|
21
23
|
...fieldPropsContext,
|
|
22
24
|
IllustratedMessage: {
|
|
@@ -51,6 +53,7 @@ var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
|
51
53
|
};
|
|
52
54
|
return /* @__PURE__ */ jsxs("div", {
|
|
53
55
|
className: wrapperProps.className,
|
|
56
|
+
inert: isSkeleton || void 0,
|
|
54
57
|
children: [/* @__PURE__ */ jsx(PropsContextProvider, {
|
|
55
58
|
props: propsContext,
|
|
56
59
|
dependencies: [controlProps["aria-describedby"]],
|
|
@@ -59,10 +62,10 @@ var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
|
59
62
|
onDrop: onDropHandler,
|
|
60
63
|
isDisabled,
|
|
61
64
|
"data-readonly": isReadOnly,
|
|
62
|
-
children: /* @__PURE__ */ jsx(IllustratedMessage, {
|
|
65
|
+
children: /* @__PURE__ */ jsx(SkeletonModeReset, { children: /* @__PURE__ */ jsx(IllustratedMessage, {
|
|
63
66
|
color: "dark",
|
|
64
67
|
children: /* @__PURE__ */ jsx(FieldErrorCaptureContext, { children })
|
|
65
|
-
})
|
|
68
|
+
}) })
|
|
66
69
|
})
|
|
67
70
|
}), /* @__PURE__ */ jsx(FieldErrorView, {})]
|
|
68
71
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDropZone.mjs","names":["styles"],"sources":["../../../../../../../src/components/FileDropZone/FileDropZone.tsx"],"sourcesContent":["import { type FC, type PropsWithChildren, useRef } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport { IllustratedMessage } from \"@/components/IllustratedMessage\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport styles from \"./FileDropZone.module.scss\";\nimport clsx from \"clsx\";\nimport type { FileInputOnChangeHandler } from \"@/components/FileField/components/FileInput\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport type { DropEvent, FocusableElement } from \"@react-types/shared\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { getAcceptedFiles } from \"@/lib/files/acceptedFiles\";\n\nexport interface FileDropZoneProps\n extends\n PropsWithClassName,\n FlowComponentProps<FocusableElement>,\n PropsWithChildren,\n Pick<Aria.InputProps, \"accept\" | \"multiple\" | \"name\">,\n Pick<Aria.DropZoneProps, \"isDisabled\"> {\n /** Called with the dropped or selected files whenever the selection changes. */\n onChange?: FileInputOnChangeHandler;\n /** Whether the component is read only. */\n isReadOnly?: boolean;\n}\n\n/** @flr-generate all */\nexport const FileDropZone: FC<FileDropZoneProps> = flowComponent(\n \"FileDropZone\",\n (props) => {\n const {\n multiple,\n accept,\n className,\n onChange: onChangeDropZone,\n children,\n name,\n isDisabled,\n isReadOnly,\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"FileDropZone\");\n\n const fileFieldRef = useRef<HTMLInputElement>(null);\n const rootClassName = clsx(\n styles.fileDropZone,\n isDisabled && styles.disabled,\n className,\n );\n\n const propsContext: PropsContext = {\n ...fieldPropsContext,\n IllustratedMessage: {\n FileField: {\n name,\n onChange: onChangeDropZone,\n ref: fileFieldRef,\n accept: accept,\n multiple: multiple,\n Button: { variant: \"outline\", color: \"dark\" },\n isDisabled,\n isReadOnly,\n \"aria-describedby\": controlProps[\"aria-describedby\"],\n },\n Heading: {\n className: styles.heading,\n },\n Icon: { className: styles.icon },\n Text: { className: styles.text },\n },\n };\n\n const onDropHandler = async (event: DropEvent) => {\n if (isReadOnly) {\n return;\n }\n\n const files = await getAcceptedFiles(event.items, accept);\n\n if (files.length > 0) {\n const fileTransfer = new DataTransfer();\n for (const file of multiple ? files : [files[0]]) {\n if (file) {\n fileTransfer.items.add(file);\n }\n }\n\n onChangeDropZone?.(fileTransfer.files);\n if (fileFieldRef.current) {\n fileFieldRef.current.files = fileTransfer.files;\n }\n }\n };\n\n return (\n <div className={wrapperProps.className}>\n <PropsContextProvider\n props={propsContext}\n dependencies={[controlProps[\"aria-describedby\"]]}\n >\n <Aria.DropZone\n className={rootClassName}\n onDrop={onDropHandler}\n isDisabled={isDisabled}\n data-readonly={isReadOnly}\n >\n <IllustratedMessage color=\"dark\">\n
|
|
1
|
+
{"version":3,"file":"FileDropZone.mjs","names":["styles"],"sources":["../../../../../../../src/components/FileDropZone/FileDropZone.tsx"],"sourcesContent":["import { type FC, type PropsWithChildren, useRef } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport { IllustratedMessage } from \"@/components/IllustratedMessage\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport styles from \"./FileDropZone.module.scss\";\nimport clsx from \"clsx\";\nimport type { FileInputOnChangeHandler } from \"@/components/FileField/components/FileInput\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport type { DropEvent, FocusableElement } from \"@react-types/shared\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { getAcceptedFiles } from \"@/lib/files/acceptedFiles\";\nimport {\n SkeletonModeReset,\n useSkeletonMode,\n} from \"@/components/SkeletonMode/skeletonModeContext\";\n\nexport interface FileDropZoneProps\n extends\n PropsWithClassName,\n FlowComponentProps<FocusableElement>,\n PropsWithChildren,\n Pick<Aria.InputProps, \"accept\" | \"multiple\" | \"name\">,\n Pick<Aria.DropZoneProps, \"isDisabled\"> {\n /** Called with the dropped or selected files whenever the selection changes. */\n onChange?: FileInputOnChangeHandler;\n /** Whether the component is read only. */\n isReadOnly?: boolean;\n}\n\n/** @flr-generate all */\nexport const FileDropZone: FC<FileDropZoneProps> = flowComponent(\n \"FileDropZone\",\n (props) => {\n const {\n multiple,\n accept,\n className,\n onChange: onChangeDropZone,\n children,\n name,\n isDisabled,\n isReadOnly,\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"FileDropZone\");\n\n const fileFieldRef = useRef<HTMLInputElement>(null);\n const isSkeleton = useSkeletonMode();\n\n const rootClassName = clsx(\n styles.fileDropZone,\n isDisabled && styles.disabled,\n isSkeleton && styles.skeleton,\n className,\n );\n\n const propsContext: PropsContext = {\n ...fieldPropsContext,\n IllustratedMessage: {\n FileField: {\n name,\n onChange: onChangeDropZone,\n ref: fileFieldRef,\n accept: accept,\n multiple: multiple,\n Button: { variant: \"outline\", color: \"dark\" },\n isDisabled,\n isReadOnly,\n \"aria-describedby\": controlProps[\"aria-describedby\"],\n },\n Heading: {\n className: styles.heading,\n },\n Icon: { className: styles.icon },\n Text: { className: styles.text },\n },\n };\n\n const onDropHandler = async (event: DropEvent) => {\n if (isReadOnly) {\n return;\n }\n\n const files = await getAcceptedFiles(event.items, accept);\n\n if (files.length > 0) {\n const fileTransfer = new DataTransfer();\n for (const file of multiple ? files : [files[0]]) {\n if (file) {\n fileTransfer.items.add(file);\n }\n }\n\n onChangeDropZone?.(fileTransfer.files);\n if (fileFieldRef.current) {\n fileFieldRef.current.files = fileTransfer.files;\n }\n }\n };\n\n return (\n <div className={wrapperProps.className} inert={isSkeleton || undefined}>\n <PropsContextProvider\n props={propsContext}\n dependencies={[controlProps[\"aria-describedby\"]]}\n >\n <Aria.DropZone\n className={rootClassName}\n onDrop={onDropHandler}\n isDisabled={isDisabled}\n data-readonly={isReadOnly}\n >\n {/* The drop zone is one skeleton surface, its content draws none. */}\n <SkeletonModeReset>\n <IllustratedMessage color=\"dark\">\n {/* Inside: IllustratedMessage clears the props context it gets. */}\n <FieldErrorCaptureContext>{children}</FieldErrorCaptureContext>\n </IllustratedMessage>\n </SkeletonModeReset>\n </Aria.DropZone>\n </PropsContextProvider>\n <FieldErrorView />\n </div>\n );\n },\n);\n\nexport default FileDropZone;\n"],"mappings":";;;;;;;;;;;;;;;AAmCA,IAAa,eAAsC,cACjD,iBACC,UAAU;CACT,MAAM,EACJ,UACA,QACA,WACA,UAAU,kBACV,UACA,MACA,YACA,eACE;CAEJ,MAAM,EACJ,gBACA,0BACA,cACA,cACA,sBACE,kBAAkB,OAAO,cAAc;CAE3C,MAAM,eAAe,OAAyB,IAAI;CAClD,MAAM,aAAa,gBAAgB;CAEnC,MAAM,gBAAgB,KACpBA,4BAAO,cACP,cAAcA,4BAAO,UACrB,cAAcA,4BAAO,UACrB,SACF;CAEA,MAAM,eAA6B;EACjC,GAAG;EACH,oBAAoB;GAClB,WAAW;IACT;IACA,UAAU;IACV,KAAK;IACG;IACE;IACV,QAAQ;KAAE,SAAS;KAAW,OAAO;IAAO;IAC5C;IACA;IACA,oBAAoB,aAAa;GACnC;GACA,SAAS,EACP,WAAWA,4BAAO,QACpB;GACA,MAAM,EAAE,WAAWA,4BAAO,KAAK;GAC/B,MAAM,EAAE,WAAWA,4BAAO,KAAK;EACjC;CACF;CAEA,MAAM,gBAAgB,OAAO,UAAqB;EAChD,IAAI,YACF;EAGF,MAAM,QAAQ,MAAM,iBAAiB,MAAM,OAAO,MAAM;EAExD,IAAI,MAAM,SAAS,GAAG;GACpB,MAAM,eAAe,IAAI,aAAa;GACtC,KAAK,MAAM,QAAQ,WAAW,QAAQ,CAAC,MAAM,EAAE,GAC7C,IAAI,MACF,aAAa,MAAM,IAAI,IAAI;GAI/B,mBAAmB,aAAa,KAAK;GACrC,IAAI,aAAa,SACf,aAAa,QAAQ,QAAQ,aAAa;EAE9C;CACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW,aAAa;EAAW,OAAO,cAAc,KAAA;EAA7D,UAAA,CACE,oBAAC,sBAAD;GACE,OAAO;GACP,cAAc,CAAC,aAAa,mBAAmB;GAE/C,UAAA,oBAAC,KAAK,UAAN;IACE,WAAW;IACX,QAAQ;IACI;IACZ,iBAAe;IAGf,UAAA,oBAAC,mBAAD,EAAA,UACE,oBAAC,oBAAD;KAAoB,OAAM;KAExB,UAAA,oBAAC,0BAAD,EAA2B,SAAmC,CAAA;IAC5C,CAAA,EACH,CAAA;GACN,CAAA;EACK,CAAA,GACtB,oBAAC,gBAAD,CAAiB,CAAA,CACd;;AAET,CACF"}
|
|
@@ -6,14 +6,18 @@ var disabled = "flow--file-drop-zone--disabled";
|
|
|
6
6
|
var icon = "flow--file-drop-zone--icon";
|
|
7
7
|
var heading = "flow--file-drop-zone--heading";
|
|
8
8
|
var text = "flow--file-drop-zone--text";
|
|
9
|
+
var skeleton = "flow--file-drop-zone--skeleton";
|
|
9
10
|
var FileDropZone_module_default = {
|
|
10
11
|
fileDropZone,
|
|
11
12
|
disabled,
|
|
12
13
|
icon,
|
|
13
14
|
heading,
|
|
14
|
-
text
|
|
15
|
+
text,
|
|
16
|
+
skeleton,
|
|
17
|
+
"skeleton-surface-shimmer": "flow--file-drop-zone--skeleton-surface-shimmer",
|
|
18
|
+
"skeleton-text-shimmer": "flow--file-drop-zone--skeleton-text-shimmer"
|
|
15
19
|
};
|
|
16
20
|
//#endregion
|
|
17
|
-
export { FileDropZone_module_default as default, disabled, fileDropZone, heading, icon, text };
|
|
21
|
+
export { FileDropZone_module_default as default, disabled, fileDropZone, heading, icon, skeleton, text };
|
|
18
22
|
|
|
19
23
|
//# sourceMappingURL=FileDropZone.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDropZone.module.mjs","names":[],"sources":["../../../../../../../src/components/FileDropZone/FileDropZone.module.scss"],"sourcesContent":[".fileDropZone {\n border-style: var(--file-drop-zone--border-style--default);\n border-width: var(--file-drop-zone--border-width);\n border-color: var(--file-drop-zone--border-color--default);\n background-color: var(--file-drop-zone--background-color--default);\n border-radius: var(--file-drop-zone--corner-radius);\n padding: var(--file-drop-zone--padding);\n transition-property: background-color, border-color;\n transition-duration: var(--transition--duration--default);\n\n &[data-focus-visible],\n &[data-drop-target]:where(:not([data-readonly])) {\n border-color: var(--file-drop-zone--border-color--target);\n border-style: var(--file-drop-zone--border-style--target);\n }\n\n &[data-drop-target]:where(:not([data-readonly])) {\n background-color: var(--file-drop-zone--background-color--target);\n }\n\n :global(.flow--form-field) {\n align-items: center;\n }\n\n &.disabled {\n background-color: var(--file-drop-zone--background-color--disabled);\n border-color: var(--file-drop-zone--border-color--disabled);\n\n .icon,\n .heading,\n .text {\n color: var(--file-drop-zone--content-color--disabled);\n }\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"FileDropZone.module.mjs","names":[],"sources":["../../../../../../../src/components/FileDropZone/FileDropZone.module.scss"],"sourcesContent":["@use \"@/styles/mixins/skeleton\";\n\n.fileDropZone {\n border-style: var(--file-drop-zone--border-style--default);\n border-width: var(--file-drop-zone--border-width);\n border-color: var(--file-drop-zone--border-color--default);\n background-color: var(--file-drop-zone--background-color--default);\n border-radius: var(--file-drop-zone--corner-radius);\n padding: var(--file-drop-zone--padding);\n transition-property: background-color, border-color;\n transition-duration: var(--transition--duration--default);\n\n &[data-focus-visible],\n &[data-drop-target]:where(:not([data-readonly])) {\n border-color: var(--file-drop-zone--border-color--target);\n border-style: var(--file-drop-zone--border-style--target);\n }\n\n &[data-drop-target]:where(:not([data-readonly])) {\n background-color: var(--file-drop-zone--background-color--target);\n }\n\n :global(.flow--form-field) {\n align-items: center;\n }\n\n &.disabled {\n background-color: var(--file-drop-zone--background-color--disabled);\n border-color: var(--file-drop-zone--border-color--disabled);\n\n .icon,\n .heading,\n .text {\n color: var(--file-drop-zone--content-color--disabled);\n }\n }\n\n /* SkeletonMode — after the states, so the surface wins over their colors */\n\n &.skeleton {\n @include skeleton.shape;\n\n --skeleton-radius: var(--file-drop-zone--corner-radius);\n }\n}\n\n@include skeleton.keyframes;\n"],"mappings":""}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
/* */
|
|
3
|
+
import { SkeletonModeReset, useSkeletonMode } from "../SkeletonMode/skeletonModeContext.mjs";
|
|
3
4
|
import { IconDanger } from "../Icon/components/icons/IconDanger.mjs";
|
|
4
5
|
import { useLocalizedStringFormatter } from "../TranslationProvider/useLocalizedStringFormatter.mjs";
|
|
5
6
|
import { Text } from "../Text/Text.mjs";
|
|
@@ -32,7 +33,8 @@ var ImageCropper = (props) => {
|
|
|
32
33
|
/** Reports every image at most once, no matter how many crops fail on it. */
|
|
33
34
|
const errorReported = useRef(false);
|
|
34
35
|
const stringFormatter = useLocalizedStringFormatter(__locale_default, "ImageCropper");
|
|
35
|
-
const
|
|
36
|
+
const isSkeleton = useSkeletonMode();
|
|
37
|
+
const rootClassName = clsx(ImageCropper_module_default.imageCropper, isSkeleton && ImageCropper_module_default.skeleton, className);
|
|
36
38
|
const reportError = (reason, message) => {
|
|
37
39
|
if (errorReported.current) return;
|
|
38
40
|
errorReported.current = true;
|
|
@@ -64,30 +66,33 @@ var ImageCropper = (props) => {
|
|
|
64
66
|
children: [/* @__PURE__ */ jsx(IconDanger, {}), /* @__PURE__ */ jsx(Text, { children: stringFormatter.format("error.text") })]
|
|
65
67
|
});
|
|
66
68
|
const errorElement = error ? errorView ?? defaultErrorView : void 0;
|
|
67
|
-
|
|
69
|
+
const errorContainer = /* @__PURE__ */ jsx("div", {
|
|
70
|
+
className: ImageCropper_module_default.errorViewContainer,
|
|
71
|
+
children: errorElement
|
|
72
|
+
});
|
|
73
|
+
const cropper = /* @__PURE__ */ jsx(Cropper, {
|
|
74
|
+
style: { containerStyle: { borderRadius: "calc(var(--image-cropper--corner-radius) - 1px)" } },
|
|
75
|
+
aspect: aspectRatio,
|
|
76
|
+
crop,
|
|
77
|
+
image: imageSrc,
|
|
78
|
+
onCropChange: setCrop,
|
|
79
|
+
zoom,
|
|
80
|
+
onZoomChange: setZoom,
|
|
81
|
+
mediaProps: { onError: () => reportError("load", `Failed to load image "${imageSrc}"`) },
|
|
82
|
+
onMediaLoaded: () => setMediaLoaded(true),
|
|
83
|
+
onCropComplete: (_, croppedAreaPixels) => {
|
|
84
|
+
if (mediaLoaded) debouncedCropComplete(croppedAreaPixels);
|
|
85
|
+
},
|
|
86
|
+
...rest
|
|
87
|
+
});
|
|
88
|
+
return /* @__PURE__ */ jsx("div", {
|
|
68
89
|
className: rootClassName,
|
|
69
90
|
style: { width },
|
|
70
|
-
|
|
91
|
+
inert: isSkeleton || void 0,
|
|
92
|
+
children: /* @__PURE__ */ jsxs(SkeletonModeReset, { children: [/* @__PURE__ */ jsx("div", {
|
|
71
93
|
className: ImageCropper_module_default.cropperContainer,
|
|
72
94
|
style: { height },
|
|
73
|
-
children: errorElement ?
|
|
74
|
-
className: ImageCropper_module_default.errorViewContainer,
|
|
75
|
-
children: errorElement
|
|
76
|
-
}) : /* @__PURE__ */ jsx(Cropper, {
|
|
77
|
-
style: { containerStyle: { borderRadius: "calc(var(--image-cropper--corner-radius) - 1px)" } },
|
|
78
|
-
aspect: aspectRatio,
|
|
79
|
-
crop,
|
|
80
|
-
image: imageSrc,
|
|
81
|
-
onCropChange: setCrop,
|
|
82
|
-
zoom,
|
|
83
|
-
onZoomChange: setZoom,
|
|
84
|
-
mediaProps: { onError: () => reportError("load", `Failed to load image "${imageSrc}"`) },
|
|
85
|
-
onMediaLoaded: () => setMediaLoaded(true),
|
|
86
|
-
onCropComplete: (_, croppedAreaPixels) => {
|
|
87
|
-
if (mediaLoaded) debouncedCropComplete(croppedAreaPixels);
|
|
88
|
-
},
|
|
89
|
-
...rest
|
|
90
|
-
})
|
|
95
|
+
children: !isSkeleton && (errorElement ? errorContainer : cropper)
|
|
91
96
|
}), !errorElement && /* @__PURE__ */ jsx(Slider, {
|
|
92
97
|
minValue: 1,
|
|
93
98
|
maxValue: 3,
|
|
@@ -96,7 +101,7 @@ var ImageCropper = (props) => {
|
|
|
96
101
|
sliderOnly: true,
|
|
97
102
|
onChange: (zoom) => setZoom(zoom),
|
|
98
103
|
"aria-label": stringFormatter.format("zoom")
|
|
99
|
-
})]
|
|
104
|
+
})] })
|
|
100
105
|
});
|
|
101
106
|
};
|
|
102
107
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageCropper.mjs","names":["locales","styles"],"sources":["../../../../../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FC,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport Cropper, { type Area, type CropperProps } from \"react-easy-crop\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport styles from \"./ImageCropper.module.scss\";\nimport { Slider } from \"@/components/Slider\";\nimport { getCroppedImageFile } from \"@/components/ImageCropper/lib/getCroppedImageFile\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./locales/*.locale.json\";\nimport { useImageSrc } from \"@/lib/hooks/useImageSrc\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { IllustratedMessage } from \"@/components/IllustratedMessage\";\nimport { IconDanger } from \"@/components/Icon/components/icons\";\nimport { Text } from \"@/components/Text\";\n\n/** Why an {@link ImageCropper} cannot work with the given image. */\nexport interface ImageCropperError {\n /**\n * `\"load\"` — the image itself could not be loaded. `\"crop\"` — the image is\n * displayed, but reading it into a canvas to produce the cropped file failed\n * (a cross-origin image without CORS headers, for example).\n */\n reason: \"load\" | \"crop\";\n /** Technical message, meant for logging — not for display. */\n message: string;\n}\n\nexport interface ImageCropperProps\n extends PropsWithClassName, Partial<Pick<CropperProps, \"cropShape\">> {\n /** The image file to crop. */\n image?: File | string;\n /** Callback on crop complete. */\n onCropComplete?: (croppedImage: File) => void;\n /**\n * Callback when the image cannot be cropped, because it failed to load or\n * could not be read.\n */\n onError?: (error: ImageCropperError) => void;\n /**\n * View that is shown instead of the cropper when the image cannot be cropped.\n * Defaults to a localized error message.\n */\n errorView?: ReactNode;\n /** The width of the component. @default 300 */\n width?: CSSProperties[\"width\"];\n /** The height of the component. @default 300 */\n height?: CSSProperties[\"height\"];\n /** The aspect ratio of the crop shape. */\n aspectRatio?: number;\n}\n\n/**\n * @flr-generate all\n * @flowStatus new\n */\nexport const ImageCropper: FC<ImageCropperProps> = (props) => {\n const {\n image,\n className,\n onCropComplete,\n onError,\n errorView,\n width = 300,\n height = 300,\n aspectRatio,\n ...rest\n } = props;\n\n const imageSrc = useImageSrc(image);\n\n const [mediaLoaded, setMediaLoaded] = useState(false);\n const [error, setError] = useState<ImageCropperError>();\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n\n /** Reports every image at most once, no matter how many crops fail on it. */\n const errorReported = useRef(false);\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"ImageCropper\");\n const rootClassName = clsx(styles.imageCropper
|
|
1
|
+
{"version":3,"file":"ImageCropper.mjs","names":["locales","styles"],"sources":["../../../../../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FC,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport Cropper, { type Area, type CropperProps } from \"react-easy-crop\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport styles from \"./ImageCropper.module.scss\";\nimport { Slider } from \"@/components/Slider\";\nimport { getCroppedImageFile } from \"@/components/ImageCropper/lib/getCroppedImageFile\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./locales/*.locale.json\";\nimport { useImageSrc } from \"@/lib/hooks/useImageSrc\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { IllustratedMessage } from \"@/components/IllustratedMessage\";\nimport { IconDanger } from \"@/components/Icon/components/icons\";\nimport { Text } from \"@/components/Text\";\nimport {\n SkeletonModeReset,\n useSkeletonMode,\n} from \"@/components/SkeletonMode/skeletonModeContext\";\n\n/** Why an {@link ImageCropper} cannot work with the given image. */\nexport interface ImageCropperError {\n /**\n * `\"load\"` — the image itself could not be loaded. `\"crop\"` — the image is\n * displayed, but reading it into a canvas to produce the cropped file failed\n * (a cross-origin image without CORS headers, for example).\n */\n reason: \"load\" | \"crop\";\n /** Technical message, meant for logging — not for display. */\n message: string;\n}\n\nexport interface ImageCropperProps\n extends PropsWithClassName, Partial<Pick<CropperProps, \"cropShape\">> {\n /** The image file to crop. */\n image?: File | string;\n /** Callback on crop complete. */\n onCropComplete?: (croppedImage: File) => void;\n /**\n * Callback when the image cannot be cropped, because it failed to load or\n * could not be read.\n */\n onError?: (error: ImageCropperError) => void;\n /**\n * View that is shown instead of the cropper when the image cannot be cropped.\n * Defaults to a localized error message.\n */\n errorView?: ReactNode;\n /** The width of the component. @default 300 */\n width?: CSSProperties[\"width\"];\n /** The height of the component. @default 300 */\n height?: CSSProperties[\"height\"];\n /** The aspect ratio of the crop shape. */\n aspectRatio?: number;\n}\n\n/**\n * @flr-generate all\n * @flowStatus new\n */\nexport const ImageCropper: FC<ImageCropperProps> = (props) => {\n const {\n image,\n className,\n onCropComplete,\n onError,\n errorView,\n width = 300,\n height = 300,\n aspectRatio,\n ...rest\n } = props;\n\n const imageSrc = useImageSrc(image);\n\n const [mediaLoaded, setMediaLoaded] = useState(false);\n const [error, setError] = useState<ImageCropperError>();\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n\n /** Reports every image at most once, no matter how many crops fail on it. */\n const errorReported = useRef(false);\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"ImageCropper\");\n const isSkeleton = useSkeletonMode();\n\n const rootClassName = clsx(\n styles.imageCropper,\n isSkeleton && styles.skeleton,\n className,\n );\n\n const reportError = (\n reason: ImageCropperError[\"reason\"],\n message: string,\n ): void => {\n if (errorReported.current) {\n return;\n }\n errorReported.current = true;\n\n const imageCropperError: ImageCropperError = { reason, message };\n setError(imageCropperError);\n onError?.(imageCropperError);\n };\n\n const debouncedCropComplete = useDebouncedCallback(\n async (croppedAreaPixels: Area) => {\n if (!croppedAreaPixels) {\n return;\n }\n\n let croppedImageFile: File;\n\n try {\n croppedImageFile = await getCroppedImageFile(\n imageSrc,\n image ?? \"\",\n croppedAreaPixels,\n );\n } catch (cause) {\n reportError(\n \"crop\",\n cause instanceof Error ? cause.message : String(cause),\n );\n return;\n }\n\n onCropComplete?.(croppedImageFile);\n },\n 500,\n {\n leading: true,\n },\n );\n\n useEffect(() => {\n setMediaLoaded(false);\n setError(undefined);\n errorReported.current = false;\n }, [imageSrc]);\n\n const defaultErrorView = (\n <IllustratedMessage color=\"danger\">\n <IconDanger />\n <Text>{stringFormatter.format(\"error.text\")}</Text>\n </IllustratedMessage>\n );\n\n const errorElement = error ? (errorView ?? defaultErrorView) : undefined;\n\n const errorContainer = (\n <div className={styles.errorViewContainer}>{errorElement}</div>\n );\n\n const cropper = (\n <Cropper\n style={{\n containerStyle: {\n borderRadius: \"calc(var(--image-cropper--corner-radius) - 1px)\",\n },\n }}\n aspect={aspectRatio}\n crop={crop}\n image={imageSrc}\n onCropChange={setCrop}\n zoom={zoom}\n onZoomChange={setZoom}\n mediaProps={{\n onError: () =>\n reportError(\"load\", `Failed to load image \"${imageSrc}\"`),\n }}\n onMediaLoaded={() => setMediaLoaded(true)}\n onCropComplete={(_, croppedAreaPixels) => {\n if (mediaLoaded) {\n debouncedCropComplete(croppedAreaPixels);\n }\n }}\n {...rest}\n />\n );\n\n return (\n <div\n className={rootClassName}\n style={{ width }}\n inert={isSkeleton || undefined}\n >\n <SkeletonModeReset>\n <div className={styles.cropperContainer} style={{ height }}>\n {/* The skeleton is one surface in the size of cropper and slider.\n It mounts no cropper, so the image is not loaded. */}\n {!isSkeleton && (errorElement ? errorContainer : cropper)}\n </div>\n {!errorElement && (\n <Slider\n minValue={1}\n maxValue={3}\n step={0.01}\n value={zoom}\n sliderOnly\n onChange={(zoom) => setZoom(zoom as number)}\n aria-label={stringFormatter.format(\"zoom\")}\n />\n )}\n </SkeletonModeReset>\n </div>\n );\n};\n\nexport default ImageCropper;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,gBAAuC,UAAU;CAC5D,MAAM,EACJ,OACA,WACA,gBACA,SACA,WACA,QAAQ,KACR,SAAS,KACT,aACA,GAAG,SACD;CAEJ,MAAM,WAAW,YAAY,KAAK;CAElC,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,OAAO,YAAY,SAA4B;CACtD,MAAM,CAAC,MAAM,WAAW,SAAS;EAAE,GAAG;EAAG,GAAG;CAAE,CAAC;CAC/C,MAAM,CAAC,MAAM,WAAW,SAAS,CAAC;;CAGlC,MAAM,gBAAgB,OAAO,KAAK;CAElC,MAAM,kBAAkB,4BAA4BA,kBAAS,cAAc;CAC3E,MAAM,aAAa,gBAAgB;CAEnC,MAAM,gBAAgB,KACpBC,4BAAO,cACP,cAAcA,4BAAO,UACrB,SACF;CAEA,MAAM,eACJ,QACA,YACS;EACT,IAAI,cAAc,SAChB;EAEF,cAAc,UAAU;EAExB,MAAM,oBAAuC;GAAE;GAAQ;EAAQ;EAC/D,SAAS,iBAAiB;EAC1B,UAAU,iBAAiB;CAC7B;CAEA,MAAM,wBAAwB,qBAC5B,OAAO,sBAA4B;EACjC,IAAI,CAAC,mBACH;EAGF,IAAI;EAEJ,IAAI;GACF,mBAAmB,MAAM,oBACvB,UACA,SAAS,IACT,iBACF;EACF,SAAS,OAAO;GACd,YACE,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;GACA;EACF;EAEA,iBAAiB,gBAAgB;CACnC,GACA,KACA,EACE,SAAS,KACX,CACF;CAEA,gBAAgB;EACd,eAAe,KAAK;EACpB,SAAS,KAAA,CAAS;EAClB,cAAc,UAAU;CAC1B,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,mBACJ,qBAAC,oBAAD;EAAoB,OAAM;EAA1B,UAAA,CACE,oBAAC,YAAD,CAAa,CAAA,GACb,oBAAC,MAAD,EAAA,UAAO,gBAAgB,OAAO,YAAY,EAAQ,CAAA,CAChC;;CAGtB,MAAM,eAAe,QAAS,aAAa,mBAAoB,KAAA;CAE/D,MAAM,iBACJ,oBAAC,OAAD;EAAK,WAAWA,4BAAO;EAAqB,UAAA;CAAkB,CAAA;CAGhE,MAAM,UACJ,oBAAC,SAAD;EACE,OAAO,EACL,gBAAgB,EACd,cAAc,kDAChB,EACF;EACA,QAAQ;EACF;EACN,OAAO;EACP,cAAc;EACR;EACN,cAAc;EACd,YAAY,EACV,eACE,YAAY,QAAQ,yBAAyB,SAAS,EAAE,EAC5D;EACA,qBAAqB,eAAe,IAAI;EACxC,iBAAiB,GAAG,sBAAsB;GACxC,IAAI,aACF,sBAAsB,iBAAiB;EAE3C;EACA,GAAI;CACL,CAAA;CAGH,OACE,oBAAC,OAAD;EACE,WAAW;EACX,OAAO,EAAE,MAAM;EACf,OAAO,cAAc,KAAA;EAErB,UAAA,qBAAC,mBAAD,EAAA,UAAA,CACE,oBAAC,OAAD;GAAK,WAAWA,4BAAO;GAAkB,OAAO,EAAE,OAAO;GAGtD,UAAA,CAAC,eAAe,eAAe,iBAAiB;EAC9C,CAAA,GACJ,CAAC,gBACA,oBAAC,QAAD;GACE,UAAU;GACV,UAAU;GACV,MAAM;GACN,OAAO;GACP,YAAA;GACA,WAAW,SAAS,QAAQ,IAAc;GAC1C,cAAY,gBAAgB,OAAO,MAAM;EAC1C,CAAA,CAEc,EAAA,CAAA;CAChB,CAAA;AAET"}
|
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
var imageCropper = "flow--image-cropper";
|
|
5
5
|
var cropperContainer = "flow--image-cropper--cropper-container";
|
|
6
6
|
var errorViewContainer = "flow--image-cropper--error-view-container";
|
|
7
|
+
var skeleton = "flow--image-cropper--skeleton";
|
|
7
8
|
var ImageCropper_module_default = {
|
|
8
9
|
imageCropper,
|
|
9
10
|
cropperContainer,
|
|
10
|
-
errorViewContainer
|
|
11
|
+
errorViewContainer,
|
|
12
|
+
skeleton,
|
|
13
|
+
"skeleton-surface-shimmer": "flow--image-cropper--skeleton-surface-shimmer",
|
|
14
|
+
"skeleton-text-shimmer": "flow--image-cropper--skeleton-text-shimmer"
|
|
11
15
|
};
|
|
12
16
|
//#endregion
|
|
13
|
-
export { cropperContainer, ImageCropper_module_default as default, errorViewContainer, imageCropper };
|
|
17
|
+
export { cropperContainer, ImageCropper_module_default as default, errorViewContainer, imageCropper, skeleton };
|
|
14
18
|
|
|
15
19
|
//# sourceMappingURL=ImageCropper.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageCropper.module.mjs","names":[],"sources":["../../../../../../../src/components/ImageCropper/ImageCropper.module.scss"],"sourcesContent":[".imageCropper {\n display: flex;\n flex-direction: column;\n gap: var(--image-cropper--spacing);\n max-width: 100%;\n\n .cropperContainer {\n position: relative;\n width: 100%;\n border-radius: var(--image-cropper--corner-radius);\n border-color: var(--image-cropper--border-color);\n border-style: var(--image-cropper--border-style);\n border-width: var(--image-cropper--border-width);\n }\n\n .errorViewContainer {\n display: flex;\n height: 100%;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n }\n}\n\n/*\n * react-easy-crop injects its stylesheet as an unlayered `<style>` element at\n * runtime, outside of Flow's build, with hard coded rgba values for the crop\n * mask and the grid. Unlayered CSS beats layered CSS regardless of specificity,\n * so these token based overrides only apply in the layered stylesheet variant\n * if they leave the cascade layer as well.\n */\n@layer flow.unlayered {\n .imageCropper {\n :global(.reactEasyCrop_CropArea) {\n color: var(--image-cropper--mask-color);\n border-color: var(--image-cropper--mask-border-color);\n box-sizing: content-box;\n }\n\n :global(.reactEasyCrop_CropAreaGrid::before) {\n border-color: var(--image-cropper--grid-color);\n border-width: var(--image-cropper--grid-width);\n }\n\n :global(.reactEasyCrop_Container) {\n border-radius: var(--image-cropper--corner-radius);\n }\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"ImageCropper.module.mjs","names":[],"sources":["../../../../../../../src/components/ImageCropper/ImageCropper.module.scss"],"sourcesContent":["@use \"@/styles/mixins/skeleton\";\n\n.imageCropper {\n display: flex;\n flex-direction: column;\n gap: var(--image-cropper--spacing);\n max-width: 100%;\n\n .cropperContainer {\n position: relative;\n width: 100%;\n border-radius: var(--image-cropper--corner-radius);\n border-color: var(--image-cropper--border-color);\n border-style: var(--image-cropper--border-style);\n border-width: var(--image-cropper--border-width);\n }\n\n .errorViewContainer {\n display: flex;\n height: 100%;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n }\n\n /* SkeletonMode */\n\n &.skeleton {\n @include skeleton.shape;\n\n --skeleton-radius: var(--image-cropper--corner-radius);\n }\n}\n\n@include skeleton.keyframes;\n\n/*\n * react-easy-crop injects its stylesheet as an unlayered `<style>` element at\n * runtime, outside of Flow's build, with hard coded rgba values for the crop\n * mask and the grid. Unlayered CSS beats layered CSS regardless of specificity,\n * so these token based overrides only apply in the layered stylesheet variant\n * if they leave the cascade layer as well.\n */\n@layer flow.unlayered {\n .imageCropper {\n :global(.reactEasyCrop_CropArea) {\n color: var(--image-cropper--mask-color);\n border-color: var(--image-cropper--mask-border-color);\n box-sizing: content-box;\n }\n\n :global(.reactEasyCrop_CropAreaGrid::before) {\n border-color: var(--image-cropper--grid-color);\n border-width: var(--image-cropper--grid-width);\n }\n\n :global(.reactEasyCrop_Container) {\n border-radius: var(--image-cropper--corner-radius);\n }\n }\n}\n"],"mappings":""}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
/* */
|
|
3
3
|
import { flowComponent } from "../../lib/componentFactory/flowComponent.mjs";
|
|
4
|
+
import { useSkeletonMode } from "../SkeletonMode/skeletonModeContext.mjs";
|
|
4
5
|
import { useLocalizedStringFormatter as useLocalizedStringFormatter$1 } from "../TranslationProvider/useLocalizedStringFormatter.mjs";
|
|
5
6
|
import __locale_default from "../../../../../_virtual/_31.locale.mjs";
|
|
6
7
|
import Kbd_module_default from "./Kbd.module.mjs";
|
|
@@ -17,7 +18,8 @@ import { useIsSSR } from "react-aria";
|
|
|
17
18
|
var Kbd = flowComponent("Kbd", (props) => {
|
|
18
19
|
const { keys, className, isDisabled, children, variant = "plain", ...rest } = props;
|
|
19
20
|
const isSsr = useIsSSR();
|
|
20
|
-
const
|
|
21
|
+
const isSkeleton = useSkeletonMode();
|
|
22
|
+
const rootClassName = clsx(Kbd_module_default.kbd, isDisabled && Kbd_module_default.disabled, Kbd_module_default[variant], isSkeleton && Kbd_module_default.skeleton, className);
|
|
21
23
|
const stringFormatter = useLocalizedStringFormatter$1(__locale_default, "Kbd");
|
|
22
24
|
const isApple = !isSsr && isAppleDevice();
|
|
23
25
|
const joinedKeys = keys?.map((key, index) => {
|
|
@@ -34,6 +36,7 @@ var Kbd = flowComponent("Kbd", (props) => {
|
|
|
34
36
|
return /* @__PURE__ */ jsx("kbd", {
|
|
35
37
|
className: rootClassName,
|
|
36
38
|
...rest,
|
|
39
|
+
inert: isSkeleton || void 0,
|
|
37
40
|
children: joinedKeys ?? children
|
|
38
41
|
});
|
|
39
42
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Kbd.mjs","names":["styles","useLocalizedStringFormatter","locales"],"sources":["../../../../../../../src/components/Kbd/Kbd.tsx"],"sourcesContent":["import { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./locales/*.locale.json\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport styles from \"./Kbd.module.scss\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport { Fragment, type PropsWithChildren } from \"react\";\nimport { isAppleDevice } from \"@react-aria/utils\";\nimport { useIsSSR } from \"react-aria\";\n\nexport interface KbdProps\n extends PropsWithClassName, FlowComponentProps, PropsWithChildren {\n /** Array of keys to be joined */\n keys?: (string | \"mod\" | \"alt\" | \"shift\")[];\n /** Whether the component is displayed as disabled */\n isDisabled?: boolean;\n /** The visual variant @default \"plain\" */\n variant?: \"plain\" | \"soft\";\n}\n\n/**\n * @flr-generate all\n * @flowStatus new\n */\nexport const Kbd = flowComponent(\"Kbd\", (props) => {\n const {\n keys,\n className,\n isDisabled,\n children,\n variant = \"plain\",\n ...rest\n } = props;\n\n const isSsr = useIsSSR();\n\n const rootClassName = clsx(\n styles.kbd,\n isDisabled && styles.disabled,\n styles[variant],\n className,\n );\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"Kbd\");\n const isApple = !isSsr && isAppleDevice();\n\n const joinedKeys = keys?.map((key, index) => {\n let formattedKey = key;\n\n if (key === \"mod\") {\n formattedKey = isApple ? \"⌘\" : stringFormatter.format(\"mod\");\n }\n\n if (key === \"alt\") {\n formattedKey = isApple ? \"⌥\" : stringFormatter.format(\"alt\");\n }\n\n if (key === \"shift\") {\n formattedKey = \"⇧\";\n }\n\n if (keys?.length === 1) {\n return <Fragment key={index}>{formattedKey}</Fragment>;\n }\n\n return (\n <Fragment key={index}>\n <kbd className={styles.kbd}>{formattedKey}</kbd>\n {index < keys.length - 1 && \" + \"}\n </Fragment>\n );\n });\n\n return (\n <kbd className={rootClassName} {...rest}>\n {joinedKeys ?? children}\n </kbd>\n );\n});\n\nexport default Kbd;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Kbd.mjs","names":["styles","useLocalizedStringFormatter","locales"],"sources":["../../../../../../../src/components/Kbd/Kbd.tsx"],"sourcesContent":["import { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./locales/*.locale.json\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport styles from \"./Kbd.module.scss\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport { Fragment, type PropsWithChildren } from \"react\";\nimport { isAppleDevice } from \"@react-aria/utils\";\nimport { useIsSSR } from \"react-aria\";\nimport { useSkeletonMode } from \"@/components/SkeletonMode/skeletonModeContext\";\n\nexport interface KbdProps\n extends PropsWithClassName, FlowComponentProps, PropsWithChildren {\n /** Array of keys to be joined */\n keys?: (string | \"mod\" | \"alt\" | \"shift\")[];\n /** Whether the component is displayed as disabled */\n isDisabled?: boolean;\n /** The visual variant @default \"plain\" */\n variant?: \"plain\" | \"soft\";\n}\n\n/**\n * @flr-generate all\n * @flowStatus new\n */\nexport const Kbd = flowComponent(\"Kbd\", (props) => {\n const {\n keys,\n className,\n isDisabled,\n children,\n variant = \"plain\",\n ...rest\n } = props;\n\n const isSsr = useIsSSR();\n const isSkeleton = useSkeletonMode();\n\n const rootClassName = clsx(\n styles.kbd,\n isDisabled && styles.disabled,\n styles[variant],\n isSkeleton && styles.skeleton,\n className,\n );\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"Kbd\");\n const isApple = !isSsr && isAppleDevice();\n\n const joinedKeys = keys?.map((key, index) => {\n let formattedKey = key;\n\n if (key === \"mod\") {\n formattedKey = isApple ? \"⌘\" : stringFormatter.format(\"mod\");\n }\n\n if (key === \"alt\") {\n formattedKey = isApple ? \"⌥\" : stringFormatter.format(\"alt\");\n }\n\n if (key === \"shift\") {\n formattedKey = \"⇧\";\n }\n\n if (keys?.length === 1) {\n return <Fragment key={index}>{formattedKey}</Fragment>;\n }\n\n return (\n <Fragment key={index}>\n <kbd className={styles.kbd}>{formattedKey}</kbd>\n {index < keys.length - 1 && \" + \"}\n </Fragment>\n );\n });\n\n return (\n <kbd className={rootClassName} {...rest} inert={isSkeleton || undefined}>\n {joinedKeys ?? children}\n </kbd>\n );\n});\n\nexport default Kbd;\n"],"mappings":";;;;;;;;;;;;;;;;;AA4BA,IAAa,MAAM,cAAc,QAAQ,UAAU;CACjD,MAAM,EACJ,MACA,WACA,YACA,UACA,UAAU,SACV,GAAG,SACD;CAEJ,MAAM,QAAQ,SAAS;CACvB,MAAM,aAAa,gBAAgB;CAEnC,MAAM,gBAAgB,KACpBA,mBAAO,KACP,cAAcA,mBAAO,UACrBA,mBAAO,UACP,cAAcA,mBAAO,UACrB,SACF;CAEA,MAAM,kBAAkBC,8BAA4BC,kBAAS,KAAK;CAClE,MAAM,UAAU,CAAC,SAAS,cAAc;CAExC,MAAM,aAAa,MAAM,KAAK,KAAK,UAAU;EAC3C,IAAI,eAAe;EAEnB,IAAI,QAAQ,OACV,eAAe,UAAU,MAAM,gBAAgB,OAAO,KAAK;EAG7D,IAAI,QAAQ,OACV,eAAe,UAAU,MAAM,gBAAgB,OAAO,KAAK;EAG7D,IAAI,QAAQ,SACV,eAAe;EAGjB,IAAI,MAAM,WAAW,GACnB,OAAO,oBAAC,UAAD,EAAA,UAAuB,aAAuB,GAA/B,KAA+B;EAGvD,OACE,qBAAC,UAAD,EAAA,UAAA,CACE,oBAAC,OAAD;GAAK,WAAWF,mBAAO;GAAM,UAAA;EAAkB,CAAA,GAC9C,QAAQ,KAAK,SAAS,KAAK,KACpB,EAAA,GAHK,KAGL;CAEd,CAAC;CAED,OACE,oBAAC,OAAD;EAAK,WAAW;EAAe,GAAI;EAAM,OAAO,cAAc,KAAA;EAC3D,UAAA,cAAc;CACZ,CAAA;AAET,CAAC"}
|
|
@@ -5,13 +5,17 @@ var kbd = "flow--kbd";
|
|
|
5
5
|
var soft = "flow--kbd--soft";
|
|
6
6
|
var plain = "flow--kbd--plain";
|
|
7
7
|
var disabled = "flow--kbd--disabled";
|
|
8
|
+
var skeleton = "flow--kbd--skeleton";
|
|
8
9
|
var Kbd_module_default = {
|
|
9
10
|
kbd,
|
|
10
11
|
soft,
|
|
11
12
|
plain,
|
|
12
|
-
disabled
|
|
13
|
+
disabled,
|
|
14
|
+
skeleton,
|
|
15
|
+
"skeleton-surface-shimmer": "flow--kbd--skeleton-surface-shimmer",
|
|
16
|
+
"skeleton-text-shimmer": "flow--kbd--skeleton-text-shimmer"
|
|
13
17
|
};
|
|
14
18
|
//#endregion
|
|
15
|
-
export { Kbd_module_default as default, disabled, kbd, plain, soft };
|
|
19
|
+
export { Kbd_module_default as default, disabled, kbd, plain, skeleton, soft };
|
|
16
20
|
|
|
17
21
|
//# sourceMappingURL=Kbd.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Kbd.module.mjs","names":[],"sources":["../../../../../../../src/components/Kbd/Kbd.module.scss"],"sourcesContent":[".kbd {\n font-family: Inter, sans-serif;\n font-size: var(--font-size-text--s);\n}\n\n:not(.kbd) > .kbd {\n &.soft {\n display: inline-block;\n line-height: var(--font-size-text--m);\n color: var(--kbd--content-color--default);\n background-color: var(--kbd--background-color--default);\n padding: var(--kbd--padding);\n padding-top: var(--kbd--padding-y-start);\n border-radius: var(--kbd--corner-radius);\n border-inline-start: var(--kbd--inner-shadow-size-x) solid\n var(--kbd--inner-shadow-color--default);\n border-inline-end: var(--kbd--inner-shadow-size-x) solid\n var(--kbd--inner-shadow-color--default);\n box-shadow: inset 0 calc(var(--kbd--inner-shadow-size-y-end) * -1) 0\n var(--kbd--inner-shadow-color--default);\n width: fit-content;\n height: fit-content;\n }\n\n &.plain {\n color: var(--kbd--content-color-plain--default);\n }\n\n &.disabled {\n &.soft {\n color: var(--kbd--content-color--disabled);\n background-color: var(--kbd--background-color--disabled);\n border-inline-start-color: var(--kbd--inner-shadow-color--disabled);\n border-inline-end-color: var(--kbd--inner-shadow-color--disabled);\n box-shadow: inset 0 calc(var(--kbd--inner-shadow-size-y-end) * -1) 0\n var(--kbd--inner-shadow-color--disabled);\n }\n\n &.plain {\n color: var(--kbd--content-color-plain--disabled);\n }\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Kbd.module.mjs","names":[],"sources":["../../../../../../../src/components/Kbd/Kbd.module.scss"],"sourcesContent":["@use \"@/styles/mixins/skeleton\";\n\n.kbd {\n font-family: Inter, sans-serif;\n font-size: var(--font-size-text--s);\n}\n\n:not(.kbd) > .kbd {\n &.soft {\n display: inline-block;\n line-height: var(--font-size-text--m);\n color: var(--kbd--content-color--default);\n background-color: var(--kbd--background-color--default);\n padding: var(--kbd--padding);\n padding-top: var(--kbd--padding-y-start);\n border-radius: var(--kbd--corner-radius);\n border-inline-start: var(--kbd--inner-shadow-size-x) solid\n var(--kbd--inner-shadow-color--default);\n border-inline-end: var(--kbd--inner-shadow-size-x) solid\n var(--kbd--inner-shadow-color--default);\n box-shadow: inset 0 calc(var(--kbd--inner-shadow-size-y-end) * -1) 0\n var(--kbd--inner-shadow-color--default);\n width: fit-content;\n height: fit-content;\n }\n\n &.plain {\n color: var(--kbd--content-color-plain--default);\n }\n\n &.disabled {\n &.soft {\n color: var(--kbd--content-color--disabled);\n background-color: var(--kbd--background-color--disabled);\n border-inline-start-color: var(--kbd--inner-shadow-color--disabled);\n border-inline-end-color: var(--kbd--inner-shadow-color--disabled);\n box-shadow: inset 0 calc(var(--kbd--inner-shadow-size-y-end) * -1) 0\n var(--kbd--inner-shadow-color--disabled);\n }\n\n &.plain {\n color: var(--kbd--content-color-plain--disabled);\n }\n }\n\n /* SkeletonMode — after the variants, and as specific as the disabled ones,\n so the surface wins over their colors */\n\n &.skeleton,\n &.skeleton.disabled {\n @include skeleton.shape;\n\n --skeleton-radius: var(--kbd--corner-radius);\n\n /* An inline box clips no overflow, so the shimmer would run past it. */\n display: inline-block;\n }\n}\n\n@include skeleton.keyframes;\n"],"mappings":""}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
/* */
|
|
3
3
|
import { extractTextFromFirstChild } from "../../lib/react/remote.mjs";
|
|
4
|
+
import { useSkeletonMode } from "../SkeletonMode/skeletonModeContext.mjs";
|
|
4
5
|
import { Text } from "../Text/Text.mjs";
|
|
5
6
|
import { Separator } from "../Separator/Separator.mjs";
|
|
6
7
|
import { Heading } from "../Heading/Heading.mjs";
|
|
@@ -9,6 +10,7 @@ import { Link } from "../Link/Link.mjs";
|
|
|
9
10
|
import { InlineCode } from "../InlineCode/InlineCode.mjs";
|
|
10
11
|
import Markdown_module_default from "./Markdown.module.mjs";
|
|
11
12
|
import { getHeadingLevelWithOffset } from "./lib/getHeadingLevelWithOffset.mjs";
|
|
13
|
+
import { SkeletonBlockText, SkeletonInlineContent } from "./components/SkeletonBlocks.mjs";
|
|
12
14
|
import clsx from "clsx";
|
|
13
15
|
import { Children, isValidElement } from "react";
|
|
14
16
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -21,6 +23,7 @@ import remarkGfm from "remark-gfm";
|
|
|
21
23
|
*/
|
|
22
24
|
var Markdown = (props) => {
|
|
23
25
|
const { children, color = "default", className, headingOffset = 0, components: customComponents, ref, allowElement, allowedElements, disallowedElements, rehypePlugins, remarkPlugins, remarkRehypeOptions, skipHtml, unwrapDisallowed, urlTransform, ...rest } = props;
|
|
26
|
+
const isSkeleton = useSkeletonMode();
|
|
24
27
|
const defaultComponents = {
|
|
25
28
|
a: (props) => /* @__PURE__ */ jsx(Link, {
|
|
26
29
|
target: "_blank",
|
|
@@ -76,15 +79,28 @@ var Markdown = (props) => {
|
|
|
76
79
|
code: String(isValidElement(preElementContent) ? preElementContent.props.children : preElementContent).trim()
|
|
77
80
|
});
|
|
78
81
|
},
|
|
79
|
-
ul: (props) => /* @__PURE__ */ jsx(
|
|
82
|
+
ul: (props) => /* @__PURE__ */ jsx(SkeletonBlockText, {
|
|
80
83
|
color,
|
|
81
84
|
children: /* @__PURE__ */ jsx("ul", { children: props.children })
|
|
82
85
|
}),
|
|
83
|
-
ol: (props) => /* @__PURE__ */ jsx(
|
|
86
|
+
ol: (props) => /* @__PURE__ */ jsx(SkeletonBlockText, {
|
|
84
87
|
color,
|
|
85
88
|
children: /* @__PURE__ */ jsx("ol", { children: props.children })
|
|
86
89
|
}),
|
|
87
|
-
|
|
90
|
+
li: ({ node: ignoredNode, children, ...props }) => /* @__PURE__ */ jsx("li", {
|
|
91
|
+
...props,
|
|
92
|
+
children: /* @__PURE__ */ jsx(SkeletonInlineContent, { children })
|
|
93
|
+
}),
|
|
94
|
+
th: ({ node: ignoredNode, children, ...props }) => /* @__PURE__ */ jsx("th", {
|
|
95
|
+
...props,
|
|
96
|
+
children: /* @__PURE__ */ jsx(SkeletonInlineContent, { children })
|
|
97
|
+
}),
|
|
98
|
+
td: ({ node: ignoredNode, children, ...props }) => /* @__PURE__ */ jsx("td", {
|
|
99
|
+
...props,
|
|
100
|
+
children: /* @__PURE__ */ jsx(SkeletonInlineContent, { children })
|
|
101
|
+
}),
|
|
102
|
+
img: ({ node: ignoredNode, ...props }) => isSkeleton ? null : /* @__PURE__ */ jsx("img", { ...props }),
|
|
103
|
+
blockquote: (props) => /* @__PURE__ */ jsx(SkeletonBlockText, {
|
|
88
104
|
color,
|
|
89
105
|
children: /* @__PURE__ */ jsx("blockquote", { children: props.children })
|
|
90
106
|
})
|