@techsio/ui-kit 0.1.0 → 0.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.
@@ -0,0 +1,211 @@
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ import { tv } from "../utils.js";
4
+ const skeletonVariants = tv({
5
+ slots: {
6
+ root: [
7
+ 'relative overflow-hidden'
8
+ ],
9
+ rectangle: [
10
+ ''
11
+ ],
12
+ circle: [
13
+ 'rounded-full',
14
+ 'shrink-0'
15
+ ],
16
+ textContainer: [
17
+ 'flex',
18
+ 'flex-col'
19
+ ],
20
+ textLine: [
21
+ 'h-skeleton-text-line',
22
+ 'rounded-skeleton-text',
23
+ 'w-full'
24
+ ]
25
+ },
26
+ variants: {
27
+ variant: {
28
+ primary: {
29
+ root: '',
30
+ circle: 'bg-skeleton-bg-primary',
31
+ rectangle: 'bg-skeleton-bg-primary',
32
+ textLine: 'bg-skeleton-bg-primary'
33
+ },
34
+ secondary: {
35
+ root: '',
36
+ circle: 'bg-skeleton-bg-secondary',
37
+ rectangle: 'bg-skeleton-bg-secondary',
38
+ textLine: 'bg-skeleton-bg-secondary'
39
+ }
40
+ },
41
+ size: {
42
+ sm: {
43
+ circle: 'size-skeleton-circle-sm',
44
+ textContainer: 'gap-skeleton-text-sm'
45
+ },
46
+ md: {
47
+ circle: 'size-skeleton-circle-md',
48
+ textContainer: 'gap-skeleton-text-md'
49
+ },
50
+ lg: {
51
+ circle: 'size-skeleton-circle-lg',
52
+ textContainer: 'gap-skeleton-text-lg'
53
+ },
54
+ xl: {
55
+ circle: 'size-skeleton-circle-xl',
56
+ textContainer: 'gap-skeleton-text-xl'
57
+ }
58
+ },
59
+ speed: {
60
+ slow: {
61
+ root: 'animate-skeleton-pulse-slow'
62
+ },
63
+ normal: {
64
+ root: 'animate-skeleton-pulse-normal'
65
+ },
66
+ fast: {
67
+ root: 'animate-skeleton-pulse-fast'
68
+ }
69
+ }
70
+ },
71
+ defaultVariants: {
72
+ variant: 'primary',
73
+ size: 'md',
74
+ speed: 'normal'
75
+ }
76
+ });
77
+ const SkeletonContext = /*#__PURE__*/ createContext(null);
78
+ const useSkeletonContext = ()=>useContext(SkeletonContext);
79
+ function useResolvedSkeletonProps(props) {
80
+ const context = useSkeletonContext();
81
+ return {
82
+ isLoaded: props.isLoaded ?? context?.isLoaded ?? false,
83
+ variant: props.variant ?? context?.variant,
84
+ speed: props.speed ?? context?.speed
85
+ };
86
+ }
87
+ function Skeleton({ isLoaded = false, variant, children, speed, className, ref, ...props }) {
88
+ const styles = skeletonVariants({
89
+ variant,
90
+ speed
91
+ });
92
+ return /*#__PURE__*/ jsx(SkeletonContext.Provider, {
93
+ value: {
94
+ isLoaded,
95
+ variant,
96
+ speed
97
+ },
98
+ children: isLoaded ? /*#__PURE__*/ jsx(Fragment, {
99
+ children: children
100
+ }) : /*#__PURE__*/ jsx("div", {
101
+ ref: ref,
102
+ className: styles.root({
103
+ className
104
+ }),
105
+ "aria-busy": "true",
106
+ "aria-label": "Loading content",
107
+ ...props,
108
+ children: children
109
+ })
110
+ });
111
+ }
112
+ Skeleton.Circle = function({ size = 'md', speed, isLoaded, variant, children, className, ref, ...props }) {
113
+ const resolved = useResolvedSkeletonProps({
114
+ isLoaded,
115
+ variant,
116
+ speed
117
+ });
118
+ const styles = skeletonVariants({
119
+ size,
120
+ variant: resolved.variant,
121
+ speed: resolved.speed
122
+ });
123
+ if (resolved.isLoaded) return /*#__PURE__*/ jsx(Fragment, {
124
+ children: children
125
+ });
126
+ return /*#__PURE__*/ jsx("div", {
127
+ ref: ref,
128
+ className: styles.root({
129
+ className: styles.circle({
130
+ className
131
+ })
132
+ }),
133
+ "aria-busy": "true",
134
+ "aria-label": "Loading content",
135
+ ...props
136
+ });
137
+ };
138
+ Skeleton.Text = function({ noOfLines = 3, size = 'md', speed, lastLineWidth = '80%', isLoaded, variant, children, containerClassName, className, ref, ...props }) {
139
+ const resolved = useResolvedSkeletonProps({
140
+ isLoaded,
141
+ variant,
142
+ speed
143
+ });
144
+ const styles = skeletonVariants({
145
+ size,
146
+ variant: resolved.variant,
147
+ speed: resolved.speed
148
+ });
149
+ if (resolved.isLoaded) return /*#__PURE__*/ jsx(Fragment, {
150
+ children: children
151
+ });
152
+ const lineCount = Number.isFinite(noOfLines) ? Math.max(1, noOfLines) : 1;
153
+ return /*#__PURE__*/ jsx("div", {
154
+ ref: ref,
155
+ className: styles.textContainer({
156
+ className: containerClassName
157
+ }),
158
+ "aria-busy": "true",
159
+ "aria-label": "Loading content",
160
+ ...props,
161
+ children: Array.from({
162
+ length: lineCount
163
+ }).map((_, index)=>{
164
+ const isLastLine = index === lineCount - 1;
165
+ const width = isLastLine && lineCount > 1 ? lastLineWidth : '100%';
166
+ return /*#__PURE__*/ jsx("div", {
167
+ className: styles.root({
168
+ className: styles.textLine({
169
+ className
170
+ })
171
+ }),
172
+ style: {
173
+ width
174
+ }
175
+ }, index);
176
+ })
177
+ });
178
+ };
179
+ Skeleton.Rectangle = function({ aspectRatio, height, width = '100%', speed, isLoaded, variant, children, className, style, ref, ...props }) {
180
+ const resolved = useResolvedSkeletonProps({
181
+ isLoaded,
182
+ variant,
183
+ speed
184
+ });
185
+ const styles = skeletonVariants({
186
+ variant: resolved.variant,
187
+ speed: resolved.speed
188
+ });
189
+ if (resolved.isLoaded) return /*#__PURE__*/ jsx(Fragment, {
190
+ children: children
191
+ });
192
+ return /*#__PURE__*/ jsx("div", {
193
+ ref: ref,
194
+ className: styles.root({
195
+ className: styles.rectangle({
196
+ className
197
+ })
198
+ }),
199
+ style: {
200
+ ...style,
201
+ width,
202
+ height,
203
+ aspectRatio
204
+ },
205
+ "aria-busy": "true",
206
+ "aria-label": "Loading content",
207
+ ...props,
208
+ children: children
209
+ });
210
+ };
211
+ export { Skeleton };
@@ -16,7 +16,7 @@ const checkboxVariants = tv({
16
16
  'appearance-none relative cursor-pointer flex-shrink-0',
17
17
  'h-checkbox w-checkbox',
18
18
  'border border-checkbox-border rounded-checkbox',
19
- 'bg-checkbox data-[state=checked]:bg-checkbox-checked border-checkbox',
19
+ 'bg-checkbox data-[state=checked]:bg-checkbox-checked',
20
20
  'after:absolute after:left-1/2 after:top-1/2 after:-translate-x-1/2 after:-translate-y-1/2',
21
21
  'data-[state=checked]:after:token-icon-checkbox text-icon-fg data-[state=checked]:text-checkbox-icon-md',
22
22
  'data-[disabled]:opacity-checkbox-disabled data-[disabled]:cursor-not-allowed data-[disabled]:grayscale',
@@ -0,0 +1,45 @@
1
+ import { type ComponentPropsWithoutRef, type ReactNode, type Ref } from 'react';
2
+ interface SkeletonRootProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
3
+ isLoaded?: boolean;
4
+ variant?: 'primary' | 'secondary';
5
+ speed?: 'slow' | 'normal' | 'fast';
6
+ children?: ReactNode;
7
+ ref?: Ref<HTMLDivElement>;
8
+ }
9
+ export declare function Skeleton({ isLoaded, variant, children, speed, className, ref, ...props }: SkeletonRootProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare namespace Skeleton {
11
+ var Circle: ({ size, speed, isLoaded, variant, children, className, ref, ...props }: SkeletonCircleProps) => import("react/jsx-runtime").JSX.Element;
12
+ var Text: ({ noOfLines, size, speed, lastLineWidth, isLoaded, variant, children, containerClassName, className, ref, ...props }: SkeletonTextProps) => import("react/jsx-runtime").JSX.Element;
13
+ var Rectangle: ({ aspectRatio, height, width, speed, isLoaded, variant, children, className, style, ref, ...props }: SkeletonRectangleProps) => import("react/jsx-runtime").JSX.Element;
14
+ }
15
+ interface SkeletonCircleProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
16
+ size?: 'sm' | 'md' | 'lg' | 'xl';
17
+ speed?: 'slow' | 'normal' | 'fast';
18
+ isLoaded?: boolean;
19
+ variant?: 'primary' | 'secondary';
20
+ children?: ReactNode;
21
+ ref?: Ref<HTMLDivElement>;
22
+ }
23
+ interface SkeletonTextProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
24
+ noOfLines?: number;
25
+ size?: 'sm' | 'md' | 'lg' | 'xl';
26
+ speed?: 'slow' | 'normal' | 'fast';
27
+ lastLineWidth?: string;
28
+ isLoaded?: boolean;
29
+ variant?: 'primary' | 'secondary';
30
+ children?: ReactNode;
31
+ containerClassName?: string;
32
+ ref?: Ref<HTMLDivElement>;
33
+ }
34
+ interface SkeletonRectangleProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
35
+ aspectRatio?: string;
36
+ height?: string;
37
+ width?: string;
38
+ speed?: 'slow' | 'normal' | 'fast';
39
+ isLoaded?: boolean;
40
+ variant?: 'primary' | 'secondary';
41
+ children?: ReactNode;
42
+ ref?: Ref<HTMLDivElement>;
43
+ }
44
+ export {};
45
+ //# sourceMappingURL=skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../../src/atoms/skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACd,KAAK,GAAG,EAGT,MAAM,OAAO,CAAA;AA0Fd,UAAU,iBACR,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;CAC1B;AAED,wBAAgB,QAAQ,CAAC,EACvB,QAAgB,EAChB,OAAO,EACP,QAAQ,EACR,KAAK,EACL,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,iBAAiB,2CAoBnB;yBA5Be,QAAQ;yFAiDrB,mBAAmB;qIAmDnB,iBAAiB;yHAkEjB,sBAAsB;;AAxIzB,UAAU,mBACR,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;CAC1B;AAqCD,UAAU,iBACR,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;CAC1B;AAwDD,UAAU,sBACR,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;CAC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techsio/ui-kit",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,75 @@
1
+ @theme static {
2
+ /* === BASE COLOR MAPPING === */
3
+ /* Background colors using reference layer */
4
+ --color-skeleton-bg: var(--color-overlay);
5
+ --color-skeleton-bg-primary: var(--color-skeleton-bg);
6
+ --color-skeleton-bg-secondary: var(--color-surface);
7
+
8
+ /* === ANIMATION === */
9
+ /* Use global motion tokens for consistent behavior */
10
+ --duration-skeleton-pulse-slow: 3s;
11
+ --duration-skeleton-pulse-normal: 2s;
12
+ --duration-skeleton-pulse-fast: 1s;
13
+
14
+ /* === SPACING === */
15
+ --spacing-skeleton-text-sm: var(--spacing-100);
16
+ --spacing-skeleton-text-md: var(--spacing-150);
17
+ --spacing-skeleton-text-lg: var(--spacing-200);
18
+ --spacing-skeleton-text-xl: var(--spacing-250);
19
+
20
+ /* === SIZING === */
21
+ --size-skeleton-circle-sm: 2rem;
22
+ --size-skeleton-circle-md: 3rem;
23
+ --size-skeleton-circle-lg: 4rem;
24
+ --size-skeleton-circle-xl: 6rem;
25
+ --height-skeleton-text-line: 1rem; /* Match text line height */
26
+
27
+ /* === BORDERS & RADIUS === */
28
+ --radius-skeleton-text: var(--radius-sm);
29
+ }
30
+
31
+ /* === ANIMATIONS === */
32
+ @keyframes skeleton-pulse {
33
+ 0%,
34
+ 100% {
35
+ opacity: 1;
36
+ }
37
+ 50% {
38
+ opacity: 0.5;
39
+ }
40
+ }
41
+
42
+ @utility animate-skeleton-pulse-slow {
43
+ animation: skeleton-pulse var(--duration-skeleton-pulse-slow) ease-in-out
44
+ infinite;
45
+ }
46
+
47
+ @utility animate-skeleton-pulse-normal {
48
+ animation: skeleton-pulse var(--duration-skeleton-pulse-normal) ease-in-out
49
+ infinite;
50
+ }
51
+
52
+ @utility animate-skeleton-pulse-fast {
53
+ animation: skeleton-pulse var(--duration-skeleton-pulse-fast) ease-in-out
54
+ infinite;
55
+ }
56
+
57
+ @layer utilities {
58
+ .animate-skeleton-pulse-slow,
59
+ .animate-skeleton-pulse-normal,
60
+ .animate-skeleton-pulse-fast {
61
+ @media (prefers-reduced-motion: reduce) {
62
+ animation: none;
63
+ opacity: 0.7;
64
+ }
65
+ }
66
+ }
67
+
68
+ /* Display reduced motion for storybook without having to
69
+ enable the prefers-reduced-motion feature in DevTools */
70
+ @layer utilities {
71
+ .force-reduced-motion {
72
+ animation: none;
73
+ opacity: 0.7;
74
+ }
75
+ }
@@ -4,6 +4,7 @@
4
4
  @import "./atoms/_input.css";
5
5
  @import "./atoms/_numeric-input.css";
6
6
  @import "./atoms/_rating.css";
7
+ @import "./atoms/_skeleton.css";
7
8
  @import "./atoms/_textarea.css";
8
9
  @import "./atoms/_tooltip.css";
9
10