@_linked/primitives 1.0.9 → 1.2.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.
Files changed (80) hide show
  1. package/.github/workflows/publish.yml +74 -7
  2. package/CHANGELOG.md +65 -0
  3. package/README.md +62 -0
  4. package/lib/cjs/components/Badge.d.ts +30 -0
  5. package/lib/cjs/components/Badge.js +64 -0
  6. package/lib/cjs/components/Badge.js.map +1 -0
  7. package/lib/cjs/components/Badge.module.css +89 -0
  8. package/lib/cjs/components/Command.d.ts +6 -6
  9. package/lib/cjs/components/ConfirmDialog.d.ts +37 -0
  10. package/lib/cjs/components/ConfirmDialog.js +68 -0
  11. package/lib/cjs/components/ConfirmDialog.js.map +1 -0
  12. package/lib/cjs/components/ConfirmDialog.module.css +22 -0
  13. package/lib/cjs/components/ImageThumb.d.ts +17 -0
  14. package/lib/cjs/components/ImageThumb.js +90 -0
  15. package/lib/cjs/components/ImageThumb.js.map +1 -0
  16. package/lib/cjs/components/ImageThumb.module.css +134 -0
  17. package/lib/cjs/components/MultiSelect.d.ts +4 -4
  18. package/lib/cjs/components/SkeletonLoader.d.ts +14 -0
  19. package/lib/cjs/components/SkeletonLoader.js +71 -0
  20. package/lib/cjs/components/SkeletonLoader.js.map +1 -0
  21. package/lib/cjs/components/SkeletonLoader.module.css +83 -0
  22. package/lib/cjs/components/Slider.js +7 -3
  23. package/lib/cjs/components/Slider.js.map +1 -1
  24. package/lib/cjs/components/Spinner.d.ts +22 -3
  25. package/lib/cjs/components/Spinner.js +55 -3
  26. package/lib/cjs/components/Spinner.js.map +1 -1
  27. package/lib/cjs/components/Spinner.module.css +57 -10
  28. package/lib/cjs/components/TruncatedText.d.ts +16 -0
  29. package/lib/cjs/components/TruncatedText.js +130 -0
  30. package/lib/cjs/components/TruncatedText.js.map +1 -0
  31. package/lib/cjs/components/TruncatedText.module.css +162 -0
  32. package/lib/cjs/hooks/useReducedMotion.d.ts +12 -0
  33. package/lib/cjs/hooks/useReducedMotion.js +35 -0
  34. package/lib/cjs/hooks/useReducedMotion.js.map +1 -0
  35. package/lib/cjs/index.d.ts +6 -0
  36. package/lib/cjs/index.js +22 -0
  37. package/lib/cjs/index.js.map +1 -1
  38. package/lib/cjs/motion.d.ts +219 -0
  39. package/lib/cjs/motion.js +154 -0
  40. package/lib/cjs/motion.js.map +1 -0
  41. package/lib/cjs/package.json +6 -6
  42. package/lib/esm/components/Badge.d.ts +30 -0
  43. package/lib/esm/components/Badge.js +13 -0
  44. package/lib/esm/components/Badge.js.map +1 -0
  45. package/lib/esm/components/Badge.module.css +89 -0
  46. package/lib/esm/components/Command.d.ts +6 -6
  47. package/lib/esm/components/ConfirmDialog.d.ts +37 -0
  48. package/lib/esm/components/ConfirmDialog.js +29 -0
  49. package/lib/esm/components/ConfirmDialog.js.map +1 -0
  50. package/lib/esm/components/ConfirmDialog.module.css +22 -0
  51. package/lib/esm/components/ImageThumb.d.ts +17 -0
  52. package/lib/esm/components/ImageThumb.js +50 -0
  53. package/lib/esm/components/ImageThumb.js.map +1 -0
  54. package/lib/esm/components/ImageThumb.module.css +134 -0
  55. package/lib/esm/components/MultiSelect.d.ts +4 -4
  56. package/lib/esm/components/SkeletonLoader.d.ts +14 -0
  57. package/lib/esm/components/SkeletonLoader.js +31 -0
  58. package/lib/esm/components/SkeletonLoader.js.map +1 -0
  59. package/lib/esm/components/SkeletonLoader.module.css +83 -0
  60. package/lib/esm/components/Slider.js +6 -2
  61. package/lib/esm/components/Slider.js.map +1 -1
  62. package/lib/esm/components/Spinner.d.ts +22 -3
  63. package/lib/esm/components/Spinner.js +22 -3
  64. package/lib/esm/components/Spinner.js.map +1 -1
  65. package/lib/esm/components/Spinner.module.css +57 -10
  66. package/lib/esm/components/TruncatedText.d.ts +16 -0
  67. package/lib/esm/components/TruncatedText.js +83 -0
  68. package/lib/esm/components/TruncatedText.js.map +1 -0
  69. package/lib/esm/components/TruncatedText.module.css +162 -0
  70. package/lib/esm/hooks/useReducedMotion.d.ts +12 -0
  71. package/lib/esm/hooks/useReducedMotion.js +32 -0
  72. package/lib/esm/hooks/useReducedMotion.js.map +1 -0
  73. package/lib/esm/index.d.ts +6 -0
  74. package/lib/esm/index.js +8 -0
  75. package/lib/esm/index.js.map +1 -1
  76. package/lib/esm/motion.d.ts +219 -0
  77. package/lib/esm/motion.js +154 -0
  78. package/lib/esm/motion.js.map +1 -0
  79. package/lib/esm/package.json +6 -6
  80. package/package.json +6 -6
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.InlineImageThumb = void 0;
40
+ const react_1 = __importStar(require("react"));
41
+ const ClassNames_1 = require("@_linked/react/utils/ClassNames");
42
+ const ImageThumb_module_css_1 = __importDefault(require("./ImageThumb.module.css"));
43
+ const ImageThumb = ({ src, size = 36, hoverSize = 280, alt = '', className = '', clickToEnlarge = true, }) => {
44
+ const [hover, setHover] = (0, react_1.useState)(false);
45
+ const [lightbox, setLightbox] = (0, react_1.useState)(false);
46
+ const [hoverPos, setHoverPos] = (0, react_1.useState)({
47
+ top: 0,
48
+ left: 0,
49
+ });
50
+ const thumbRef = (0, react_1.useRef)(null);
51
+ const handleMouseEnter = (0, react_1.useCallback)(() => {
52
+ if (thumbRef.current) {
53
+ const rect = thumbRef.current.getBoundingClientRect();
54
+ // Position the hover preview to the right of the thumbnail,
55
+ // but clamp so it doesn't overflow the viewport
56
+ const left = Math.min(rect.right + 8, window.innerWidth - hoverSize - 16);
57
+ const top = Math.max(8, Math.min(rect.top - hoverSize / 2 + size / 2, window.innerHeight - hoverSize - 16));
58
+ setHoverPos({ top, left });
59
+ }
60
+ setHover(true);
61
+ }, [hoverSize, size]);
62
+ const handleClick = (0, react_1.useCallback)((e) => {
63
+ if (clickToEnlarge) {
64
+ e.stopPropagation();
65
+ setHover(false);
66
+ setLightbox(true);
67
+ }
68
+ }, [clickToEnlarge]);
69
+ const closeLightbox = (0, react_1.useCallback)(() => {
70
+ setLightbox(false);
71
+ }, []);
72
+ return (react_1.default.createElement(react_1.default.Fragment, null,
73
+ react_1.default.createElement("span", { className: (0, ClassNames_1.cl)(ImageThumb_module_css_1.default.root, className), onMouseEnter: handleMouseEnter, onMouseLeave: () => setHover(false) },
74
+ react_1.default.createElement("img", { ref: thumbRef, src: src, alt: alt, className: ImageThumb_module_css_1.default.thumb, style: { width: size, height: size }, onClick: handleClick, loading: "lazy" }),
75
+ hover && !lightbox && (react_1.default.createElement("div", { className: (0, ClassNames_1.cl)(ImageThumb_module_css_1.default.hoverPreview, hover && ImageThumb_module_css_1.default.visible), style: {
76
+ top: hoverPos.top,
77
+ left: hoverPos.left,
78
+ width: hoverSize,
79
+ height: hoverSize,
80
+ } },
81
+ react_1.default.createElement("img", { src: src, alt: alt, className: ImageThumb_module_css_1.default.hoverPreviewImage, style: { width: hoverSize, height: hoverSize } })))),
82
+ lightbox && (react_1.default.createElement("div", { className: ImageThumb_module_css_1.default.previewOverlay, onClick: closeLightbox },
83
+ react_1.default.createElement("div", { className: (0, ClassNames_1.cl)(ImageThumb_module_css_1.default.previewBackdrop, ImageThumb_module_css_1.default.visible) }),
84
+ react_1.default.createElement("img", { src: src, alt: alt, className: (0, ClassNames_1.cl)(ImageThumb_module_css_1.default.previewImage, ImageThumb_module_css_1.default.visible) })))));
85
+ };
86
+ /** Small inline thumbnail for use inside chips, badges, and dropdown options */
87
+ const InlineImageThumb = ({ src, alt = '', }) => (react_1.default.createElement("img", { src: src, alt: alt, className: ImageThumb_module_css_1.default.inlineThumb, loading: "lazy" }));
88
+ exports.InlineImageThumb = InlineImageThumb;
89
+ exports.default = ImageThumb;
90
+ //# sourceMappingURL=ImageThumb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageThumb.js","sourceRoot":"","sources":["../../../src/components/ImageThumb.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ @import './helpers/mixins.css';
2
+ @import '@_linked/css/package.css';
3
+
4
+ /* ============================================================================
5
+ ImageThumb.module.css
6
+
7
+ Thumbnail image with enlarged hover preview.
8
+ Uses semantic tokens from theme.css.
9
+ ============================================================================ */
10
+
11
+ .root {
12
+ position: relative;
13
+ display: inline-flex;
14
+ flex-shrink: 0;
15
+ }
16
+
17
+ /* === Thumbnail === */
18
+ .thumb {
19
+ object-fit: cover;
20
+ border-radius: var(--radius-field);
21
+ border: 1px solid var(--surface-border);
22
+ cursor: pointer;
23
+ transition: box-shadow var(--transition-fast), transform var(--transition-fast);
24
+ background-color: var(--section-bg);
25
+ }
26
+
27
+ .thumb:hover {
28
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
29
+ transform: scale(1.05);
30
+ }
31
+
32
+ /* === Hover Preview Overlay === */
33
+ .previewOverlay {
34
+ position: fixed;
35
+ inset: 0;
36
+ z-index: 9999;
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ pointer-events: none;
41
+ }
42
+
43
+ .previewBackdrop {
44
+ position: absolute;
45
+ inset: 0;
46
+ background: rgba(0, 0, 0, 0.4);
47
+ opacity: 0;
48
+ transition: opacity 0.2s ease;
49
+ pointer-events: auto;
50
+ }
51
+
52
+ .previewBackdrop.visible {
53
+ opacity: 1;
54
+ }
55
+
56
+ .previewImage {
57
+ position: relative;
58
+ max-width: 80vw;
59
+ max-height: 80vh;
60
+ object-fit: contain;
61
+ border-radius: var(--radius-box);
62
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
63
+ z-index: 1;
64
+ opacity: 0;
65
+ transform: scale(0.92);
66
+ transition: opacity 0.2s ease, transform 0.2s ease;
67
+ pointer-events: auto;
68
+ }
69
+
70
+ .previewImage.visible {
71
+ opacity: 1;
72
+ transform: scale(1);
73
+ }
74
+
75
+ /* === Hover tooltip preview (positioned near thumbnail) === */
76
+ .hoverPreview {
77
+ position: fixed;
78
+ z-index: 10000;
79
+ pointer-events: none;
80
+ opacity: 0;
81
+ transform: scale(0.95);
82
+ transition: opacity 0.15s ease, transform 0.15s ease;
83
+ border-radius: var(--radius-box);
84
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
85
+ overflow: hidden;
86
+ background-color: var(--section-bg);
87
+ }
88
+
89
+ .hoverPreview.visible {
90
+ opacity: 1;
91
+ transform: scale(1);
92
+ }
93
+
94
+ .hoverPreviewImage {
95
+ display: block;
96
+ object-fit: cover;
97
+ border-radius: var(--radius-box);
98
+ }
99
+
100
+ /* === Dark mode adjustments === */
101
+ [data-theme='dark'] .thumb {
102
+ border-color: var(--surface-border);
103
+ }
104
+
105
+ [data-theme='dark'] .previewBackdrop {
106
+ background: rgba(0, 0, 0, 0.6);
107
+ }
108
+
109
+ [data-theme='dark'] .hoverPreview {
110
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
111
+ }
112
+
113
+ /* === Inline variant (used inside chips/badges) === */
114
+ .inlineThumb {
115
+ width: 20px;
116
+ height: 20px;
117
+ object-fit: cover;
118
+ border-radius: var(--radius-selector, 3px);
119
+ border: 1px solid var(--surface-border);
120
+ vertical-align: middle;
121
+ flex-shrink: 0;
122
+ }
123
+
124
+ /* === Reduced motion === */
125
+ @media (prefers-reduced-motion: reduce) {
126
+ .thumb:hover {
127
+ transform: none;
128
+ }
129
+ .hoverPreview,
130
+ .previewImage,
131
+ .previewBackdrop {
132
+ transition: none;
133
+ }
134
+ }
@@ -14,7 +14,7 @@ declare const Input: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<React.D
14
14
  ref?: React.Ref<HTMLInputElement>;
15
15
  } & {
16
16
  asChild?: boolean;
17
- }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "value" | "onChange"> & {
17
+ }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "onChange" | "value"> & {
18
18
  value?: string;
19
19
  onValueChange?: (search: string) => void;
20
20
  } & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -36,7 +36,7 @@ declare const Item: React.ForwardRefExoticComponent<{
36
36
  ref?: React.Ref<HTMLDivElement>;
37
37
  } & {
38
38
  asChild?: boolean;
39
- }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "disabled" | "value" | "onSelect"> & {
39
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "onSelect" | "disabled" | "value"> & {
40
40
  disabled?: boolean;
41
41
  onSelect?: (value: string) => void;
42
42
  value?: string;
@@ -53,7 +53,7 @@ export declare const MultiSelect: {
53
53
  ref?: React.Ref<HTMLInputElement>;
54
54
  } & {
55
55
  asChild?: boolean;
56
- }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "value" | "onChange"> & {
56
+ }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "onChange" | "value"> & {
57
57
  value?: string;
58
58
  onValueChange?: (search: string) => void;
59
59
  } & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -75,7 +75,7 @@ export declare const MultiSelect: {
75
75
  ref?: React.Ref<HTMLDivElement>;
76
76
  } & {
77
77
  asChild?: boolean;
78
- }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "disabled" | "value" | "onSelect"> & {
78
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "onSelect" | "disabled" | "value"> & {
79
79
  disabled?: boolean;
80
80
  onSelect?: (value: string) => void;
81
81
  value?: string;
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ interface SkeletonLoaderProps {
3
+ width?: string | number;
4
+ height?: string | number;
5
+ borderRadius?: string | number;
6
+ className?: string;
7
+ lines?: number;
8
+ animated?: boolean;
9
+ }
10
+ export declare function SkeletonLoader({ width, height, borderRadius, className, lines, animated, }: SkeletonLoaderProps): React.JSX.Element;
11
+ export declare function TableRowSkeleton({ columns }: {
12
+ columns?: number;
13
+ }): React.JSX.Element;
14
+ export default SkeletonLoader;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.SkeletonLoader = SkeletonLoader;
40
+ exports.TableRowSkeleton = TableRowSkeleton;
41
+ const React = __importStar(require("react"));
42
+ const SkeletonLoader_module_css_1 = __importDefault(require("./SkeletonLoader.module.css"));
43
+ function SkeletonLoader({ width = '100%', height = 18, borderRadius = 4, className = '', lines = 1, animated = true, }) {
44
+ if (lines === 1) {
45
+ return (React.createElement("div", { className: `${SkeletonLoader_module_css_1.default.skeleton} ${animated ? SkeletonLoader_module_css_1.default.animated : ''} ${className}`, style: {
46
+ width,
47
+ height,
48
+ borderRadius,
49
+ } }));
50
+ }
51
+ return (React.createElement("div", { className: className }, Array.from({ length: lines }, (_, index) => (React.createElement("div", { key: index, className: `${SkeletonLoader_module_css_1.default.skeleton} ${animated ? SkeletonLoader_module_css_1.default.animated : ''} ${index < lines - 1 ? SkeletonLoader_module_css_1.default.marginBottom : ''}`, style: {
52
+ width: index === lines - 1 ? '60%' : '100%',
53
+ height,
54
+ borderRadius,
55
+ } })))));
56
+ }
57
+ // Table row skeleton component
58
+ function TableRowSkeleton({ columns = 5 }) {
59
+ return (React.createElement("tr", { className: SkeletonLoader_module_css_1.default.tableRow },
60
+ React.createElement("td", { className: SkeletonLoader_module_css_1.default.tableCell, style: { width: '48px' } },
61
+ React.createElement(SkeletonLoader, { width: 18, height: 18, borderRadius: 6 })),
62
+ Array.from({ length: columns }, (_, index) => (React.createElement("td", { key: index, className: SkeletonLoader_module_css_1.default.tableCell },
63
+ React.createElement(SkeletonLoader, { width: "18vw", height: 18 })))),
64
+ React.createElement("td", { className: SkeletonLoader_module_css_1.default.tableCell },
65
+ React.createElement("div", { className: SkeletonLoader_module_css_1.default.actionButtons },
66
+ React.createElement(SkeletonLoader, { width: 22, height: 18, borderRadius: 6 }),
67
+ React.createElement(SkeletonLoader, { width: 22, height: 18, borderRadius: 6 }),
68
+ React.createElement(SkeletonLoader, { width: 22, height: 18, borderRadius: 6 })))));
69
+ }
70
+ exports.default = SkeletonLoader;
71
+ //# sourceMappingURL=SkeletonLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkeletonLoader.js","sourceRoot":"","sources":["../../../src/components/SkeletonLoader.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,wCAoCC;AAGD,4CAoBC;AAvED,6CAA+B;AAC/B,4FAAgD;AAWhD,SAAgB,cAAc,CAAC,EAC7B,KAAK,GAAG,MAAM,EACd,MAAM,GAAG,EAAE,EACX,YAAY,GAAG,CAAC,EAChB,SAAS,GAAG,EAAE,EACd,KAAK,GAAG,CAAC,EACT,QAAQ,GAAG,IAAI,GACK;IACpB,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,CACL,6BACE,SAAS,EAAE,GAAG,mCAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,mCAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,EAAE,EAC7E,KAAK,EAAE;gBACL,KAAK;gBACL,MAAM;gBACN,YAAY;aACb,GACD,CACH,CAAC;IACJ,CAAC;IAED,OAAO,CACL,6BAAK,SAAS,EAAE,SAAS,IACtB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAC3C,6BACE,GAAG,EAAE,KAAK,EACV,SAAS,EAAE,GAAG,mCAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,mCAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,mCAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAC/G,KAAK,EAAE;YACL,KAAK,EAAE,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;YAC3C,MAAM;YACN,YAAY;SACb,GACD,CACH,CAAC,CACE,CACP,CAAC;AACJ,CAAC;AAED,+BAA+B;AAC/B,SAAgB,gBAAgB,CAAC,EAAE,OAAO,GAAG,CAAC,EAAwB;IACpE,OAAO,CACL,4BAAI,SAAS,EAAE,mCAAK,CAAC,QAAQ;QAC3B,4BAAI,SAAS,EAAE,mCAAK,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;YACtD,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI,CACvD;QACJ,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAC7C,4BAAI,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,mCAAK,CAAC,SAAS;YACxC,oBAAC,cAAc,IAAC,KAAK,EAAC,MAAM,EAAC,MAAM,EAAE,EAAE,GAAI,CACxC,CACN,CAAC;QACF,4BAAI,SAAS,EAAE,mCAAK,CAAC,SAAS;YAC5B,6BAAK,SAAS,EAAE,mCAAK,CAAC,aAAa;gBACjC,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI;gBAC1D,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI;gBAC1D,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI,CACtD,CACH,CACF,CACN,CAAC;AACJ,CAAC;AAED,kBAAe,cAAc,CAAC"}
@@ -0,0 +1,83 @@
1
+ @import './helpers/mixins.css';
2
+ @import '@_linked/css/package.css';
3
+
4
+ /* ============================================================================
5
+ SkeletonLoader.module.css
6
+
7
+ Loading placeholder with shimmer animation.
8
+ Uses semantic tokens from theme.css.
9
+ ============================================================================ */
10
+
11
+ /* === Base Skeleton === */
12
+ .skeleton {
13
+ background: linear-gradient(
14
+ 90deg,
15
+ var(--skeleton-bg, var(--color-gray-100)) 25%,
16
+ var(--skeleton-highlight, var(--color-gray-200)) 50%,
17
+ var(--skeleton-bg, var(--color-gray-100)) 75%
18
+ );
19
+ background-size: 200% 100%;
20
+ animation: shimmer 1.5s infinite;
21
+ display: inline-block;
22
+ border-radius: var(--radius-selector, 4px);
23
+ }
24
+
25
+ /* === Animation Variant === */
26
+ .animated {
27
+ animation: shimmer 1.5s infinite;
28
+ }
29
+
30
+ /* === Spacing === */
31
+ .marginBottom {
32
+ margin-bottom: 0.5rem;
33
+ }
34
+
35
+ /* === Table Row Skeleton === */
36
+ .tableRow {
37
+ border-bottom: 1px solid var(--skeleton-row-border, var(--table-row-border));
38
+ }
39
+
40
+ /* === Table Cell Skeleton === */
41
+ .tableCell {
42
+ padding: var(--skeleton-row-padding-y, var(--surface-gap)) var(--skeleton-row-padding-x, var(--space-sm));
43
+ vertical-align: middle;
44
+ }
45
+
46
+ /* === Action Buttons Container === */
47
+ .actionButtons {
48
+ display: flex;
49
+ gap: var(--space-sm);
50
+ align-items: center;
51
+ justify-content: flex-end;
52
+ }
53
+
54
+ /* ============================================================================
55
+ Dark Mode
56
+ ============================================================================ */
57
+
58
+ [data-theme='dark'] .skeleton {
59
+ background: linear-gradient(
60
+ 90deg,
61
+ var(--skeleton-bg, var(--color-gray-800)) 25%,
62
+ var(--skeleton-highlight, var(--color-gray-700)) 50%,
63
+ var(--skeleton-bg, var(--color-gray-800)) 75%
64
+ );
65
+ background-size: 200% 100%;
66
+ }
67
+
68
+ [data-theme='dark'] .tableRow {
69
+ border-bottom-color: var(--skeleton-row-border, var(--table-row-border));
70
+ }
71
+
72
+ /* ============================================================================
73
+ Shimmer Animation
74
+ ============================================================================ */
75
+
76
+ @keyframes shimmer {
77
+ 0% {
78
+ background-position: -200% 0;
79
+ }
80
+ 100% {
81
+ background-position: 200% 0;
82
+ }
83
+ }
@@ -67,11 +67,15 @@ exports.Range = Range;
67
67
  const Thumb = extend(SliderPrimitive.Thumb, Slider_module_css_1.default.Thumb);
68
68
  exports.Thumb = Thumb;
69
69
  const Root = React.forwardRef((_a, ref) => {
70
- var { className } = _a, props = __rest(_a, ["className"]);
71
- return (React.createElement(SliderPrimitive.Root, Object.assign({ ref: ref, className: (0, ClassNames_1.cl)(Slider_module_css_1.default.Root, className) }, props),
70
+ var { className, 'aria-label': ariaLabel, 'aria-disabled': ariaDisabled } = _a, props = __rest(_a, ["className", 'aria-label', 'aria-disabled']);
71
+ return (
72
+ // Self-contained single-thumb slider. Forward the accessible name / disabled
73
+ // state to the actual `role="slider"` element (the Thumb) rather than the Root,
74
+ // so `getByRole('slider', { name })` and assistive tech can address the control.
75
+ React.createElement(SliderPrimitive.Root, Object.assign({ ref: ref, className: (0, ClassNames_1.cl)(Slider_module_css_1.default.Root, className) }, props),
72
76
  React.createElement(Track, null,
73
77
  React.createElement(Range, null)),
74
- React.createElement(Thumb, null)));
78
+ React.createElement(Thumb, { "aria-label": ariaLabel, "aria-disabled": ariaDisabled })));
75
79
  });
76
80
  exports.Root = Root;
77
81
  Root.displayName = SliderPrimitive.Root.displayName;
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/components/Slider.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA+B;AAE/B,4EAAwC;AACxC,gEAAqD;AAErD,wEAA0D;AAE1D,SAAS,MAAM,CACb,SAAY,EACZ,aAAqB;IAErB,IAAI,QAAQ,GAAG,KAAK,CAAC,UAAU,CAG7B,CAAC,EAAuB,EAAE,GAAG,EAAE,EAAE;YAAhC,EAAE,SAAS,OAAY,EAAP,KAAK,cAArB,aAAuB,CAAF;QACtB,OAAA,KAAK,CAAC,aAAa,CAAC,SAAS,kBAC3B,GAAG,EACH,SAAS,EAAE,IAAA,eAAE,EAAC,aAAa,EAAE,SAAS,CAAC,IACpC,KAAK,EACR,CAAA;KAAA,CACH,CAAC;IACF,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;IAC7C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,2BAAK,CAAC,KAAK,CAAC,CAAC;AA4B1C,sBAAK;AA3BpB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,2BAAK,CAAC,KAAK,CAAC,CAAC;AA2BnC,sBAAK;AA1B3B,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,2BAAK,CAAC,KAAK,CAAC,CAAC;AA0B5B,sBAAK;AAxBlC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAG3B,CAAC,EAAuB,EAAE,GAAG,EAAE,EAAE;QAAhC,EAAE,SAAS,OAAY,EAAP,KAAK,cAArB,aAAuB,CAAF;IAAY,OAAA,CAClC,oBAAC,eAAe,CAAC,IAAI,kBACnB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,eAAE,EAAC,2BAAK,CAAC,IAAI,EAAE,SAAS,CAAC,IAChC,KAAK;QAET,oBAAC,KAAK;YACJ,oBAAC,KAAK,OAAG,CACH;QACR,oBAAC,KAAK,OAAG,CACY,CACxB,CAAA;CAAA,CAAC,CAAC;AAUM,oBAAI;AATb,IAAI,CAAC,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC;AAEvC,QAAA,MAAM,GAAG;IACpB,IAAI;IACJ,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC"}
1
+ {"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/components/Slider.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA+B;AAE/B,4EAAwC;AACxC,gEAAqD;AAErD,wEAA0D;AAE1D,SAAS,MAAM,CACb,SAAY,EACZ,aAAqB;IAErB,IAAI,QAAQ,GAAG,KAAK,CAAC,UAAU,CAG7B,CAAC,EAAuB,EAAE,GAAG,EAAE,EAAE;YAAhC,EAAE,SAAS,OAAY,EAAP,KAAK,cAArB,aAAuB,CAAF;QACtB,OAAA,KAAK,CAAC,aAAa,CAAC,SAAS,kBAC3B,GAAG,EACH,SAAS,EAAE,IAAA,eAAE,EAAC,aAAa,EAAE,SAAS,CAAC,IACpC,KAAK,EACR,CAAA;KAAA,CACH,CAAC;IACF,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;IAC7C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,2BAAK,CAAC,KAAK,CAAC,CAAC;AA+B1C,sBAAK;AA9BpB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,2BAAK,CAAC,KAAK,CAAC,CAAC;AA8BnC,sBAAK;AA7B3B,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,2BAAK,CAAC,KAAK,CAAC,CAAC;AA6B5B,sBAAK;AA3BlC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAG3B,CAAC,EAA+E,EAAE,GAAG,EAAE,EAAE;QAAxF,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,OAAY,EAAP,KAAK,cAA7E,4CAA+E,CAAF;IAAY,OAAA;IAC1F,6EAA6E;IAC7E,gFAAgF;IAChF,iFAAiF;IACjF,oBAAC,eAAe,CAAC,IAAI,kBACnB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,eAAE,EAAC,2BAAK,CAAC,IAAI,EAAE,SAAS,CAAC,IAChC,KAAK;QAET,oBAAC,KAAK;YACJ,oBAAC,KAAK,OAAG,CACH;QACR,oBAAC,KAAK,kBAAa,SAAS,mBAAiB,YAAY,GAAI,CACxC,CACxB,CAAA;CAAA,CAAC,CAAC;AAUM,oBAAI;AATb,IAAI,CAAC,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC;AAEvC,QAAA,MAAM,GAAG;IACpB,IAAI;IACJ,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC"}
@@ -1,4 +1,23 @@
1
- import React from 'react';
2
- export declare function Spinner({ active }: {
1
+ import * as React from 'react';
2
+ export interface SpinnerProps {
3
+ /** Render nothing when false. */
3
4
  active?: boolean;
4
- }): React.JSX.Element;
5
+ size?: 'small' | 'medium' | 'large' | 'xlarge';
6
+ className?: string;
7
+ /** Announced to assistive technology. */
8
+ label?: string;
9
+ }
10
+ /**
11
+ * A loading indicator: a ring that inherits its colour, so it reads on any background.
12
+ *
13
+ * Two things it does that a bare CSS spin does not. It honours
14
+ * `prefers-reduced-motion` — a spinner is the most common thing to make someone with
15
+ * vestibular sensitivity look away — showing a still ring rather than nothing, so the
16
+ * "busy" signal survives. And it renders **nothing** when inactive, so it can be dropped
17
+ * into a scroll sentinel or a button without reserving space it is not using.
18
+ *
19
+ * The ring is an inner element rather than a border on the container. A border on the
20
+ * container is distorted the moment a flex parent stretches it; an explicitly sized inner
21
+ * element stays circular.
22
+ */
23
+ export declare function Spinner({ active, size, className, label, }: SpinnerProps): React.JSX.Element;
@@ -1,12 +1,64 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.Spinner = Spinner;
7
- const react_1 = __importDefault(require("react"));
40
+ const React = __importStar(require("react"));
8
41
  const Spinner_module_css_1 = __importDefault(require("./Spinner.module.css"));
9
- function Spinner({ active = true }) {
10
- return (react_1.default.createElement("div", { className: [Spinner_module_css_1.default.spinner, active && Spinner_module_css_1.default.active].join(' '), role: "progressbar", "aria-busy": active ? 'true' : 'false' }));
42
+ const ClassNames_1 = require("@_linked/react/utils/ClassNames");
43
+ const useReducedMotion_js_1 = require("../hooks/useReducedMotion.js");
44
+ /**
45
+ * A loading indicator: a ring that inherits its colour, so it reads on any background.
46
+ *
47
+ * Two things it does that a bare CSS spin does not. It honours
48
+ * `prefers-reduced-motion` — a spinner is the most common thing to make someone with
49
+ * vestibular sensitivity look away — showing a still ring rather than nothing, so the
50
+ * "busy" signal survives. And it renders **nothing** when inactive, so it can be dropped
51
+ * into a scroll sentinel or a button without reserving space it is not using.
52
+ *
53
+ * The ring is an inner element rather than a border on the container. A border on the
54
+ * container is distorted the moment a flex parent stretches it; an explicitly sized inner
55
+ * element stays circular.
56
+ */
57
+ function Spinner({ active = true, size = 'small', className, label = 'Loading', }) {
58
+ const reducedMotion = (0, useReducedMotion_js_1.useReducedMotion)();
59
+ if (!active)
60
+ return null;
61
+ return (React.createElement("div", { className: (0, ClassNames_1.cl)(Spinner_module_css_1.default.spinner, Spinner_module_css_1.default[size], className), role: "progressbar", "aria-busy": "true", "aria-label": label },
62
+ React.createElement("span", { className: (0, ClassNames_1.cl)(Spinner_module_css_1.default.ring, reducedMotion && Spinner_module_css_1.default.reducedMotion), "aria-hidden": "true" })));
11
63
  }
12
64
  //# sourceMappingURL=Spinner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../../src/components/Spinner.tsx"],"names":[],"mappings":";;;;;AAGA,0BAQC;AAXD,kDAA0B;AAC1B,8EAAyC;AAEzC,SAAgB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE;IACvC,OAAO,CACL,uCACE,SAAS,EAAE,CAAC,4BAAK,CAAC,OAAO,EAAE,MAAM,IAAI,4BAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC5D,IAAI,EAAC,aAAa,eACP,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,GACpC,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../../src/components/Spinner.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,0BAuBC;AAlDD,6CAA+B;AAC/B,8EAAyC;AACzC,gEAAmD;AACnD,sEAA8D;AAW9D;;;;;;;;;;;;GAYG;AACH,SAAgB,OAAO,CAAC,EACtB,MAAM,GAAG,IAAI,EACb,IAAI,GAAG,OAAO,EACd,SAAS,EACT,KAAK,GAAG,SAAS,GACJ;IACb,MAAM,aAAa,GAAG,IAAA,sCAAgB,GAAE,CAAC;IAEzC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,6BACE,SAAS,EAAE,IAAA,eAAE,EAAC,4BAAK,CAAC,OAAO,EAAE,4BAAK,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,EACpD,IAAI,EAAC,aAAa,eACR,MAAM,gBACJ,KAAK;QAEjB,8BACE,SAAS,EAAE,IAAA,eAAE,EAAC,4BAAK,CAAC,IAAI,EAAE,aAAa,IAAI,4BAAK,CAAC,aAAa,CAAC,iBACnD,MAAM,GAClB,CACE,CACP,CAAC;AACJ,CAAC"}
@@ -2,20 +2,67 @@
2
2
  @import '@_linked/css/package.css';
3
3
 
4
4
  .spinner {
5
- border: var(--spinner-border-width, 4px) solid
6
- var(--spinner-track-color, transparent);
7
- border-top-color: var(--spinner-indicator-color, var(--meter-indicator-bg));
8
- border-radius: 50%;
5
+ display: inline-flex;
6
+ /* Never grow or shrink in a flex parent — that would distort the ring. */
7
+ flex: 0 0 auto;
8
+ align-items: center;
9
+ justify-content: center;
10
+ color: var(--spinner-indicator-color, var(--meter-indicator-bg, currentColor));
11
+ }
12
+
13
+ /* Sized explicitly rather than filling the container, so the ring stays a circle even when
14
+ a flex parent stretches the box around it. */
15
+ .ring {
16
+ box-sizing: border-box;
17
+ flex: 0 0 auto;
9
18
  width: var(--spinner-size, --spacing(4));
10
19
  height: var(--spinner-size, --spacing(4));
11
- animation: spin var(--spinner-animation-duration, 1s) linear infinite;
20
+ border-radius: 50%;
21
+ border: var(--spinner-border-width, 2px) solid currentColor;
22
+ border-top-color: var(--spinner-track-color, transparent);
23
+ opacity: 0.85;
24
+ animation: spinnerRotate var(--spinner-animation-duration, 0.7s) linear infinite;
12
25
  }
13
26
 
14
- @keyframes spin {
15
- 0% {
16
- transform: rotate(0deg);
17
- }
18
- 100% {
27
+ @keyframes spinnerRotate {
28
+ to {
19
29
  transform: rotate(360deg);
20
30
  }
21
31
  }
32
+
33
+ /* Size variants. Each sets `--spinner-size`, so a consumer that sets the variable directly
34
+ still wins — the variants are a shorthand for it, not a replacement. */
35
+ .small {
36
+ --spinner-size: --spacing(4);
37
+ }
38
+ .medium {
39
+ --spinner-size: --spacing(6);
40
+ }
41
+ .large {
42
+ --spinner-size: --spacing(8);
43
+ --spinner-border-width: 3px;
44
+ }
45
+ .xlarge {
46
+ --spinner-size: --spacing(12);
47
+ --spinner-border-width: 3px;
48
+ }
49
+
50
+ .small,
51
+ .medium,
52
+ .large,
53
+ .xlarge {
54
+ width: var(--spinner-size);
55
+ height: var(--spinner-size);
56
+ }
57
+
58
+ /* Reduced motion: freeze the ring, keep it visible. Removing it entirely would remove the
59
+ only signal that something is loading. */
60
+ .reducedMotion {
61
+ animation: none;
62
+ }
63
+
64
+ @media (prefers-reduced-motion: reduce) {
65
+ .ring {
66
+ animation: none;
67
+ }
68
+ }