@galyan/ui 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/package.json +53 -22
  2. package/.turbo/turbo-build.log +0 -20
  3. package/eslint.config.mjs +0 -4
  4. package/src/accordion/Accordion.tsx +0 -88
  5. package/src/accordion/accordion.css +0 -78
  6. package/src/accordion/index.ts +0 -2
  7. package/src/animatednumber/AnimatedNumber.tsx +0 -71
  8. package/src/animatednumber/index.ts +0 -2
  9. package/src/banner/Banner.tsx +0 -84
  10. package/src/banner/banner.css +0 -56
  11. package/src/banner/index.ts +0 -2
  12. package/src/breadcrumb/Breadcrumb.tsx +0 -94
  13. package/src/breadcrumb/breadcrumb.css +0 -58
  14. package/src/breadcrumb/index.ts +0 -2
  15. package/src/button/Button.tsx +0 -98
  16. package/src/button/button.css +0 -190
  17. package/src/button/index.ts +0 -2
  18. package/src/button.tsx +0 -20
  19. package/src/calendar/Calendar.tsx +0 -190
  20. package/src/calendar/calendar.css +0 -142
  21. package/src/calendar/index.ts +0 -2
  22. package/src/card/Card.tsx +0 -88
  23. package/src/card/card.css +0 -115
  24. package/src/card/index.ts +0 -2
  25. package/src/card.tsx +0 -27
  26. package/src/chart/Chart.tsx +0 -186
  27. package/src/chart/index.ts +0 -2
  28. package/src/checkbox/Checkbox.tsx +0 -101
  29. package/src/checkbox/checkbox.css +0 -76
  30. package/src/checkbox/index.ts +0 -2
  31. package/src/chips/Chips.tsx +0 -146
  32. package/src/chips/chips.css +0 -90
  33. package/src/chips/index.ts +0 -2
  34. package/src/code.tsx +0 -11
  35. package/src/datepicker/DatePicker.tsx +0 -104
  36. package/src/datepicker/datepicker.css +0 -22
  37. package/src/datepicker/index.ts +0 -2
  38. package/src/dragdrop/DragDrop.tsx +0 -168
  39. package/src/dragdrop/dragdrop.css +0 -122
  40. package/src/dragdrop/index.ts +0 -2
  41. package/src/dropdown/Dropdown.tsx +0 -176
  42. package/src/dropdown/dropdown.css +0 -118
  43. package/src/dropdown/index.ts +0 -2
  44. package/src/fileupload/FileUpload.tsx +0 -144
  45. package/src/fileupload/fileupload.css +0 -118
  46. package/src/fileupload/index.ts +0 -2
  47. package/src/index.ts +0 -28
  48. package/src/input/Input.tsx +0 -121
  49. package/src/input/index.ts +0 -2
  50. package/src/input/input.css +0 -120
  51. package/src/menu/Menu.tsx +0 -118
  52. package/src/menu/index.ts +0 -2
  53. package/src/menu/menu.css +0 -117
  54. package/src/modal/Modal.tsx +0 -103
  55. package/src/modal/index.ts +0 -2
  56. package/src/modal/modal.css +0 -79
  57. package/src/progressbar/ProgressBar.tsx +0 -68
  58. package/src/progressbar/index.ts +0 -2
  59. package/src/progressbar/progressbar.css +0 -73
  60. package/src/radiogroup/RadioGroup.tsx +0 -73
  61. package/src/radiogroup/index.ts +0 -2
  62. package/src/radiogroup/radiogroup.css +0 -80
  63. package/src/skeleton/Skeleton.tsx +0 -61
  64. package/src/skeleton/index.ts +0 -2
  65. package/src/skeleton/skeleton.css +0 -46
  66. package/src/spinner/Spinner.tsx +0 -29
  67. package/src/spinner/index.ts +0 -2
  68. package/src/spinner/spinner.css +0 -39
  69. package/src/stepper/Stepper.tsx +0 -127
  70. package/src/stepper/index.ts +0 -2
  71. package/src/stepper/stepper.css +0 -141
  72. package/src/tab/Tabs.tsx +0 -71
  73. package/src/tab/index.ts +0 -2
  74. package/src/tab/tab.css +0 -92
  75. package/src/table/Table.tsx +0 -205
  76. package/src/table/index.ts +0 -2
  77. package/src/table/table.css +0 -119
  78. package/src/textarea/Textarea.tsx +0 -102
  79. package/src/textarea/index.ts +0 -2
  80. package/src/textarea/textarea.css +0 -85
  81. package/src/toaster/Toaster.tsx +0 -108
  82. package/src/toaster/index.ts +0 -2
  83. package/src/toaster/toaster.css +0 -113
  84. package/src/toggle/Toggle.tsx +0 -88
  85. package/src/toggle/index.ts +0 -2
  86. package/src/toggle/toggle.css +0 -63
  87. package/src/typography/Typography.tsx +0 -58
  88. package/src/typography/index.ts +0 -2
  89. package/src/typography/typography.css +0 -102
  90. package/tsconfig.json +0 -13
@@ -1,68 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import './progressbar.css';
5
-
6
- export type ProgressSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
7
- export type ProgressColor = 'primary' | 'success' | 'warning' | 'danger' | 'gradient';
8
-
9
- export interface ProgressBarProps {
10
- value?: number;
11
- max?: number;
12
- size?: ProgressSize;
13
- color?: ProgressColor;
14
- label?: string;
15
- showValue?: boolean;
16
- striped?: boolean;
17
- indeterminate?: boolean;
18
- className?: string;
19
- }
20
-
21
- export function ProgressBar({
22
- value = 0,
23
- max = 100,
24
- size = 'md',
25
- color = 'primary',
26
- label,
27
- showValue = false,
28
- striped = false,
29
- indeterminate = false,
30
- className = '',
31
- }: ProgressBarProps) {
32
- const pct = Math.min(Math.max((value / max) * 100, 0), 100);
33
-
34
- const fillClasses = [
35
- 'gy-progress-fill',
36
- color !== 'primary' ? `gy-progress-fill--${color}` : '',
37
- striped ? 'gy-progress-fill--striped' : '',
38
- indeterminate ? 'gy-progress-fill--indeterminate' : '',
39
- ]
40
- .filter(Boolean)
41
- .join(' ');
42
-
43
- return (
44
- <div className={`gy-progress ${className}`}>
45
- {(label || showValue) && (
46
- <div className="gy-progress-header">
47
- {label && <span className="gy-progress-label">{label}</span>}
48
- {showValue && !indeterminate && (
49
- <span className="gy-progress-value">{Math.round(pct)}%</span>
50
- )}
51
- </div>
52
- )}
53
- <div
54
- className={`gy-progress-track gy-progress-track--${size}`}
55
- role="progressbar"
56
- aria-valuenow={indeterminate ? undefined : value}
57
- aria-valuemin={0}
58
- aria-valuemax={max}
59
- aria-label={label ?? 'Progress'}
60
- >
61
- <div
62
- className={fillClasses}
63
- style={{ width: indeterminate ? undefined : `${pct}%` }}
64
- />
65
- </div>
66
- </div>
67
- );
68
- }
@@ -1,2 +0,0 @@
1
- export { ProgressBar } from './ProgressBar';
2
- export type { ProgressBarProps, ProgressSize, ProgressColor } from './ProgressBar';
@@ -1,73 +0,0 @@
1
- /* ── ProgressBar ─────────────────────────────────────────────────────────── */
2
- .gy-progress {
3
- display: flex;
4
- flex-direction: column;
5
- gap: var(--gy-spacing-1-5);
6
- width: 100%;
7
- }
8
-
9
- .gy-progress-header {
10
- display: flex;
11
- justify-content: space-between;
12
- align-items: center;
13
- }
14
-
15
- .gy-progress-label {
16
- font-size: var(--gy-font-size-sm);
17
- font-weight: var(--gy-font-weight-medium);
18
- color: var(--gy-text);
19
- }
20
-
21
- .gy-progress-value {
22
- font-size: var(--gy-font-size-sm);
23
- color: var(--gy-text-muted);
24
- font-weight: var(--gy-font-weight-medium);
25
- }
26
-
27
- .gy-progress-track {
28
- background: var(--gy-background-muted);
29
- border-radius: var(--gy-radius-full);
30
- overflow: hidden;
31
- }
32
-
33
- .gy-progress-track--xs { height: 0.25rem; }
34
- .gy-progress-track--sm { height: 0.375rem; }
35
- .gy-progress-track--md { height: 0.5rem; }
36
- .gy-progress-track--lg { height: 0.75rem; }
37
- .gy-progress-track--xl { height: 1rem; }
38
-
39
- .gy-progress-fill {
40
- height: 100%;
41
- border-radius: var(--gy-radius-full);
42
- background: var(--gy-primary);
43
- transition: width var(--gy-duration-slow) var(--gy-ease-out);
44
- }
45
-
46
- .gy-progress-fill--success { background: var(--gy-success); }
47
- .gy-progress-fill--warning { background: var(--gy-warning); }
48
- .gy-progress-fill--danger { background: var(--gy-danger); }
49
-
50
- .gy-progress-fill--gradient {
51
- background: var(--gy-gradient-primary);
52
- }
53
-
54
- .gy-progress-fill--striped {
55
- background-image: repeating-linear-gradient(
56
- -45deg,
57
- transparent,
58
- transparent 8px,
59
- rgba(255,255,255,0.2) 8px,
60
- rgba(255,255,255,0.2) 16px
61
- );
62
- background-size: 32px 32px;
63
- }
64
-
65
- .gy-progress-fill--indeterminate {
66
- width: 40% !important;
67
- animation: gy-progress-indeterminate 1.5s var(--gy-ease-in-out) infinite;
68
- }
69
-
70
- @keyframes gy-progress-indeterminate {
71
- 0% { transform: translateX(-100%); }
72
- 100% { transform: translateX(250%); }
73
- }
@@ -1,73 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useId } from 'react';
4
- import './radiogroup.css';
5
-
6
- export interface RadioOption {
7
- value: string;
8
- label: React.ReactNode;
9
- disabled?: boolean;
10
- }
11
-
12
- export interface RadioGroupProps {
13
- options: RadioOption[];
14
- value?: string;
15
- defaultValue?: string;
16
- onChange?: (value: string) => void;
17
- orientation?: 'horizontal' | 'vertical';
18
- groupLabel?: string;
19
- name?: string;
20
- disabled?: boolean;
21
- className?: string;
22
- }
23
-
24
- export function RadioGroup({
25
- options,
26
- value,
27
- defaultValue,
28
- onChange,
29
- orientation = 'vertical',
30
- groupLabel,
31
- name,
32
- disabled = false,
33
- className = '',
34
- }: RadioGroupProps) {
35
- const uid = useId();
36
- const groupName = name ?? uid;
37
-
38
- return (
39
- <div
40
- role="radiogroup"
41
- aria-label={typeof groupLabel === 'string' ? groupLabel : undefined}
42
- className={`gy-radio-group ${orientation === 'horizontal' ? 'gy-radio-group--horizontal' : ''} ${className}`}
43
- >
44
- {groupLabel && <div className="gy-radio-group-label">{groupLabel}</div>}
45
- {options.map((opt) => {
46
- const isChecked = value !== undefined ? value === opt.value : undefined;
47
- const isDisabled = disabled || opt.disabled;
48
-
49
- return (
50
- <label
51
- key={opt.value}
52
- className={`gy-radio ${isDisabled ? 'gy-radio--disabled' : ''}`}
53
- >
54
- <input
55
- type="radio"
56
- name={groupName}
57
- value={opt.value}
58
- checked={isChecked}
59
- defaultChecked={defaultValue === opt.value}
60
- disabled={isDisabled}
61
- className="gy-radio-input"
62
- onChange={() => onChange?.(opt.value)}
63
- />
64
- <span className={`gy-radio-circle ${isChecked ? 'gy-radio-circle--checked' : ''}`}>
65
- {isChecked && <span className="gy-radio-dot" />}
66
- </span>
67
- <span className="gy-radio-label">{opt.label}</span>
68
- </label>
69
- );
70
- })}
71
- </div>
72
- );
73
- }
@@ -1,2 +0,0 @@
1
- export { RadioGroup } from './RadioGroup';
2
- export type { RadioGroupProps, RadioOption } from './RadioGroup';
@@ -1,80 +0,0 @@
1
- /* ── RadioGroup ───────────────────────────────────────────────────────────── */
2
- .gy-radio-group {
3
- display: flex;
4
- flex-direction: column;
5
- gap: var(--gy-spacing-2);
6
- }
7
-
8
- .gy-radio-group--horizontal {
9
- flex-direction: row;
10
- flex-wrap: wrap;
11
- }
12
-
13
- .gy-radio-group-label {
14
- font-size: var(--gy-font-size-sm);
15
- font-weight: var(--gy-font-weight-semibold);
16
- color: var(--gy-text);
17
- margin-bottom: var(--gy-spacing-1);
18
- }
19
-
20
- .gy-radio {
21
- display: inline-flex;
22
- align-items: center;
23
- gap: var(--gy-spacing-2);
24
- cursor: pointer;
25
- }
26
-
27
- .gy-radio--disabled {
28
- cursor: not-allowed;
29
- opacity: 0.5;
30
- }
31
-
32
- .gy-radio-input {
33
- position: absolute;
34
- opacity: 0;
35
- width: 0;
36
- height: 0;
37
- }
38
-
39
- .gy-radio-circle {
40
- display: flex;
41
- align-items: center;
42
- justify-content: center;
43
- width: 1.125rem;
44
- height: 1.125rem;
45
- border-radius: 50%;
46
- border: 2px solid var(--gy-border-strong);
47
- background: var(--gy-surface);
48
- flex-shrink: 0;
49
- transition:
50
- border-color var(--gy-duration-fast) var(--gy-ease-in-out),
51
- box-shadow var(--gy-duration-fast) var(--gy-ease-in-out);
52
- }
53
-
54
- .gy-radio:not(.gy-radio--disabled):hover .gy-radio-circle {
55
- border-color: var(--gy-primary);
56
- }
57
-
58
- .gy-radio-input:focus-visible + .gy-radio-circle {
59
- box-shadow: 0 0 0 3px var(--gy-focus-ring);
60
- border-color: var(--gy-primary);
61
- }
62
-
63
- .gy-radio-circle--checked {
64
- border-color: var(--gy-primary);
65
- }
66
-
67
- .gy-radio-dot {
68
- width: 0.5rem;
69
- height: 0.5rem;
70
- border-radius: 50%;
71
- background: var(--gy-primary);
72
- animation: gy-zoom-in var(--gy-duration-fast) var(--gy-ease-spring);
73
- }
74
-
75
- .gy-radio-label {
76
- font-size: var(--gy-font-size-sm);
77
- font-weight: var(--gy-font-weight-medium);
78
- color: var(--gy-text);
79
- line-height: 1.4;
80
- }
@@ -1,61 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import './skeleton.css';
5
-
6
- export type SkeletonShape = 'text' | 'circle' | 'rect' | 'card';
7
- export type SkeletonAnimation = 'wave' | 'pulse' | 'none';
8
-
9
- export interface SkeletonProps {
10
- shape?: SkeletonShape;
11
- animation?: SkeletonAnimation;
12
- width?: string | number;
13
- height?: string | number;
14
- className?: string;
15
- lines?: number;
16
- gap?: string;
17
- }
18
-
19
- export function Skeleton({
20
- shape = 'rect',
21
- animation = 'wave',
22
- width,
23
- height,
24
- className = '',
25
- lines,
26
- gap = '0.5rem',
27
- }: SkeletonProps) {
28
- const classes = [
29
- 'gy-skeleton',
30
- `gy-skeleton--${shape}`,
31
- animation !== 'none' ? `gy-skeleton--${animation}` : '',
32
- !width ? 'gy-skeleton--w-full' : '',
33
- className,
34
- ]
35
- .filter(Boolean)
36
- .join(' ');
37
-
38
- const style: React.CSSProperties = {
39
- width: width,
40
- height: height,
41
- };
42
-
43
- if (lines) {
44
- return (
45
- <div style={{ display: 'flex', flexDirection: 'column', gap }}>
46
- {Array.from({ length: lines }).map((_, i) => (
47
- <div
48
- key={i}
49
- className={`gy-skeleton gy-skeleton--text ${animation !== 'none' ? `gy-skeleton--${animation}` : ''} ${
50
- i === lines - 1 ? 'gy-skeleton--w-3-4' : 'gy-skeleton--w-full'
51
- }`}
52
- style={{ height: height ?? '1em' }}
53
- aria-hidden="true"
54
- />
55
- ))}
56
- </div>
57
- );
58
- }
59
-
60
- return <div className={classes} style={style} aria-hidden="true" />;
61
- }
@@ -1,2 +0,0 @@
1
- export { Skeleton } from './Skeleton';
2
- export type { SkeletonProps, SkeletonShape, SkeletonAnimation } from './Skeleton';
@@ -1,46 +0,0 @@
1
- /* ── Skeleton ─────────────────────────────────────────────────────────────── */
2
- .gy-skeleton {
3
- background: var(--gy-skeleton-base);
4
- border-radius: var(--gy-radius-md);
5
- overflow: hidden;
6
- position: relative;
7
- }
8
-
9
- /* Wave animation */
10
- .gy-skeleton--wave::after {
11
- content: '';
12
- position: absolute;
13
- inset: 0;
14
- background: linear-gradient(90deg, transparent 25%, var(--gy-border) 50%, transparent 75%);
15
- background-size: 200% 100%;
16
- animation: gy-wave 1.5s var(--gy-ease) infinite;
17
- }
18
-
19
- /* Pulse animation */
20
- .gy-skeleton--pulse {
21
- animation: gy-pulse 1.5s var(--gy-ease-in-out) infinite;
22
- }
23
-
24
- /* Shapes */
25
- .gy-skeleton--text {
26
- height: 1em;
27
- border-radius: var(--gy-radius-sm);
28
- }
29
-
30
- .gy-skeleton--circle {
31
- border-radius: 50%;
32
- }
33
-
34
- .gy-skeleton--rect {
35
- border-radius: var(--gy-radius-md);
36
- }
37
-
38
- .gy-skeleton--card {
39
- border-radius: var(--gy-radius-xl);
40
- }
41
-
42
- /* Width presets */
43
- .gy-skeleton--w-full { width: 100%; }
44
- .gy-skeleton--w-3-4 { width: 75%; }
45
- .gy-skeleton--w-1-2 { width: 50%; }
46
- .gy-skeleton--w-1-4 { width: 25%; }
@@ -1,29 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import './spinner.css';
5
-
6
- export type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
7
- export type SpinnerColor = 'primary' | 'white' | 'neutral';
8
-
9
- export interface SpinnerProps {
10
- size?: SpinnerSize;
11
- color?: SpinnerColor;
12
- label?: string;
13
- className?: string;
14
- }
15
-
16
- export function Spinner({ size = 'md', color = 'primary', label, className = '' }: SpinnerProps) {
17
- return (
18
- <div className={`gy-spinner-container ${className}`}>
19
- <span
20
- className={`gy-spinner gy-spinner--${size} gy-spinner--${color}`}
21
- role="status"
22
- aria-label={label ?? 'Loading...'}
23
- >
24
- <span className="gy-spinner__circle" aria-hidden="true" />
25
- </span>
26
- {label && <span className="gy-spinner__label">{label}</span>}
27
- </div>
28
- );
29
- }
@@ -1,2 +0,0 @@
1
- export { Spinner } from './Spinner';
2
- export type { SpinnerProps, SpinnerSize, SpinnerColor } from './Spinner';
@@ -1,39 +0,0 @@
1
- /* ── Spinner ──────────────────────────────────────────────────────────────── */
2
- .gy-spinner {
3
- display: inline-flex;
4
- align-items: center;
5
- justify-content: center;
6
- flex-shrink: 0;
7
- }
8
-
9
- .gy-spinner__circle {
10
- border-radius: 50%;
11
- border-style: solid;
12
- border-color: var(--gy-primary-muted);
13
- border-top-color: var(--gy-primary);
14
- animation: gy-spin var(--gy-duration-slower) linear infinite;
15
- }
16
-
17
- .gy-spinner--xs .gy-spinner__circle { width: 1rem; height: 1rem; border-width: 2px; }
18
- .gy-spinner--sm .gy-spinner__circle { width: 1.25rem; height: 1.25rem; border-width: 2px; }
19
- .gy-spinner--md .gy-spinner__circle { width: 1.5rem; height: 1.5rem; border-width: 2.5px; }
20
- .gy-spinner--lg .gy-spinner__circle { width: 2rem; height: 2rem; border-width: 3px; }
21
- .gy-spinner--xl .gy-spinner__circle { width: 3rem; height: 3rem; border-width: 4px; }
22
-
23
- /* Color variants */
24
- .gy-spinner--primary .gy-spinner__circle { border-color: var(--gy-primary-muted); border-top-color: var(--gy-primary); }
25
- .gy-spinner--white .gy-spinner__circle { border-color: rgba(255,255,255,0.3); border-top-color: #ffffff; }
26
- .gy-spinner--neutral .gy-spinner__circle { border-color: var(--gy-border); border-top-color: var(--gy-text-muted); }
27
-
28
- .gy-spinner__label {
29
- margin-top: var(--gy-spacing-2);
30
- font-size: var(--gy-font-size-xs);
31
- color: var(--gy-text-subtle);
32
- text-align: center;
33
- }
34
-
35
- .gy-spinner-container {
36
- display: inline-flex;
37
- flex-direction: column;
38
- align-items: center;
39
- }
@@ -1,127 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useState } from 'react';
4
- import './stepper.css';
5
-
6
- export type StepStatus = 'upcoming' | 'active' | 'completed' | 'error';
7
-
8
- export interface Step {
9
- id: string;
10
- label: string;
11
- description?: string;
12
- content?: React.ReactNode;
13
- optional?: boolean;
14
- }
15
-
16
- export interface StepperProps {
17
- steps: Step[];
18
- activeStep?: number;
19
- defaultStep?: number;
20
- /** 'linear' = must complete in order; 'free' = can jump to any step */
21
- variant?: 'linear' | 'free';
22
- orientation?: 'horizontal' | 'vertical';
23
- onStepChange?: (index: number) => void;
24
- onComplete?: () => void;
25
- className?: string;
26
- }
27
-
28
- const CheckIcon = () => (
29
- <svg width="14" height="11" viewBox="0 0 14 11" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
30
- <polyline points="1,5 5,9 13,1" />
31
- </svg>
32
- );
33
-
34
- const ErrorIcon = () => (
35
- <svg width="12" height="12" viewBox="0 0 12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
36
- <line x1="2" y1="2" x2="10" y2="10" /><line x1="10" y1="2" x2="2" y2="10" />
37
- </svg>
38
- );
39
-
40
- export function Stepper({
41
- steps,
42
- activeStep: controlledStep,
43
- defaultStep = 0,
44
- variant = 'linear',
45
- orientation = 'horizontal',
46
- onStepChange,
47
- onComplete,
48
- className = '',
49
- }: StepperProps) {
50
- const [internalStep, setInternalStep] = useState(defaultStep);
51
- const current = controlledStep ?? internalStep;
52
-
53
- const goTo = (idx: number) => {
54
- if (variant === 'linear' && idx > current + 1) return;
55
- if (idx < 0 || idx >= steps.length) return;
56
- setInternalStep(idx);
57
- onStepChange?.(idx);
58
- };
59
-
60
- const next = () => {
61
- if (current === steps.length - 1) {
62
- onComplete?.();
63
- } else {
64
- goTo(current + 1);
65
- }
66
- };
67
-
68
- const prev = () => goTo(current - 1);
69
-
70
- const getStatus = (idx: number): StepStatus => {
71
- if (idx < current) return 'completed';
72
- if (idx === current) return 'active';
73
- return 'upcoming';
74
- };
75
-
76
- return (
77
- <div className={`gy-stepper ${orientation === 'vertical' ? 'gy-stepper--vertical' : ''} ${className}`}>
78
- {/* Step Indicators */}
79
- <div className={`gy-stepper ${orientation === 'vertical' ? 'gy-stepper--vertical' : ''}`} style={{ width: '100%' }}>
80
- {steps.map((step, idx) => {
81
- const status = getStatus(idx);
82
- const isClickable = variant === 'free' || idx <= current;
83
-
84
- return (
85
- <React.Fragment key={step.id}>
86
- <div className="gy-stepper-item">
87
- <span
88
- className={[
89
- 'gy-stepper-indicator',
90
- `gy-stepper-indicator--${status}`,
91
- isClickable ? 'gy-stepper-indicator--clickable' : '',
92
- ]
93
- .filter(Boolean)
94
- .join(' ')}
95
- onClick={() => isClickable && goTo(idx)}
96
- role={isClickable ? 'button' : undefined}
97
- tabIndex={isClickable ? 0 : undefined}
98
- onKeyDown={isClickable ? (e) => { if (e.key === 'Enter') goTo(idx); } : undefined}
99
- aria-label={`Step ${idx + 1}: ${step.label}`}
100
- aria-current={status === 'active' ? 'step' : undefined}
101
- >
102
- {status === 'completed' ? <CheckIcon /> : status === 'error' ? <ErrorIcon /> : idx + 1}
103
- </span>
104
- <div>
105
- <div className={`gy-stepper-label gy-stepper-label--${status}`}>{step.label}</div>
106
- {step.optional && <div className="gy-stepper-description">Optional</div>}
107
- {step.description && <div className="gy-stepper-description">{step.description}</div>}
108
- </div>
109
- </div>
110
-
111
- {idx < steps.length - 1 && (
112
- <div className={`gy-stepper-connector ${idx < current ? 'gy-stepper-connector--completed' : ''}`} />
113
- )}
114
- </React.Fragment>
115
- );
116
- })}
117
- </div>
118
-
119
- {/* Active Panel */}
120
- {steps[current]?.content && (
121
- <div key={current} className="gy-stepper-panel">
122
- {steps[current].content}
123
- </div>
124
- )}
125
- </div>
126
- );
127
- }
@@ -1,2 +0,0 @@
1
- export { Stepper } from './Stepper';
2
- export type { StepperProps, Step, StepStatus } from './Stepper';