@freightos/freightwind 1.0.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 (198) hide show
  1. package/dist/cjs/components/accordion.js +57 -0
  2. package/dist/cjs/components/alert.js +76 -0
  3. package/dist/cjs/components/aspect-ratio.js +39 -0
  4. package/dist/cjs/components/avatar.js +75 -0
  5. package/dist/cjs/components/badge.js +24 -0
  6. package/dist/cjs/components/breadcrumb.js +65 -0
  7. package/dist/cjs/components/button.js +76 -0
  8. package/dist/cjs/components/calendar.js +106 -0
  9. package/dist/cjs/components/card.js +59 -0
  10. package/dist/cjs/components/chart.js +176 -0
  11. package/dist/cjs/components/checkbox.js +44 -0
  12. package/dist/cjs/components/chip.js +26 -0
  13. package/dist/cjs/components/collapsible.js +43 -0
  14. package/dist/cjs/components/command.js +73 -0
  15. package/dist/cjs/components/context-menu.js +83 -0
  16. package/dist/cjs/components/country-select.js +155 -0
  17. package/dist/cjs/components/date-picker.js +59 -0
  18. package/dist/cjs/components/date-range-picker.js +59 -0
  19. package/dist/cjs/components/date-time-picker.js +106 -0
  20. package/dist/cjs/components/dialog.js +70 -0
  21. package/dist/cjs/components/drawer.js +68 -0
  22. package/dist/cjs/components/dropdown-menu.js +85 -0
  23. package/dist/cjs/components/empty.js +42 -0
  24. package/dist/cjs/components/file-preview.js +73 -0
  25. package/dist/cjs/components/form.js +106 -0
  26. package/dist/cjs/components/inline-edit.js +83 -0
  27. package/dist/cjs/components/input-group.js +70 -0
  28. package/dist/cjs/components/input-otp.js +58 -0
  29. package/dist/cjs/components/input.js +57 -0
  30. package/dist/cjs/components/label.js +45 -0
  31. package/dist/cjs/components/menubar.js +96 -0
  32. package/dist/cjs/components/navigation-menu.js +68 -0
  33. package/dist/cjs/components/pagination.js +65 -0
  34. package/dist/cjs/components/phone-input.js +218 -0
  35. package/dist/cjs/components/popover.js +49 -0
  36. package/dist/cjs/components/progress.js +43 -0
  37. package/dist/cjs/components/radio-button-group.js +84 -0
  38. package/dist/cjs/components/radio-group.js +50 -0
  39. package/dist/cjs/components/resizable.js +47 -0
  40. package/dist/cjs/components/rich-text-editor.js +152 -0
  41. package/dist/cjs/components/route.js +47 -0
  42. package/dist/cjs/components/scroll-area.js +48 -0
  43. package/dist/cjs/components/select.js +71 -0
  44. package/dist/cjs/components/separator.js +43 -0
  45. package/dist/cjs/components/sheet.js +245 -0
  46. package/dist/cjs/components/skeleton.js +8 -0
  47. package/dist/cjs/components/slider.js +47 -0
  48. package/dist/cjs/components/sonner.js +25 -0
  49. package/dist/cjs/components/spinner.js +25 -0
  50. package/dist/cjs/components/stepper.js +99 -0
  51. package/dist/cjs/components/steps.js +127 -0
  52. package/dist/cjs/components/switch.js +66 -0
  53. package/dist/cjs/components/table.js +66 -0
  54. package/dist/cjs/components/tabs.js +51 -0
  55. package/dist/cjs/components/textarea.js +44 -0
  56. package/dist/cjs/components/time-picker.js +110 -0
  57. package/dist/cjs/components/toast.js +75 -0
  58. package/dist/cjs/components/toaster.js +12 -0
  59. package/dist/cjs/components/toggle-group.js +58 -0
  60. package/dist/cjs/components/toggle.js +62 -0
  61. package/dist/cjs/components/tooltip.js +49 -0
  62. package/dist/cjs/hooks/use-toast.js +166 -0
  63. package/dist/cjs/index.js +88 -0
  64. package/dist/cjs/lib/countryUtils.js +93 -0
  65. package/dist/cjs/lib/utils.js +8 -0
  66. package/dist/esm/components/accordion.js +18 -0
  67. package/dist/esm/components/alert.js +39 -0
  68. package/dist/esm/components/aspect-ratio.js +3 -0
  69. package/dist/esm/components/avatar.js +37 -0
  70. package/dist/esm/components/badge.js +20 -0
  71. package/dist/esm/components/breadcrumb.js +23 -0
  72. package/dist/esm/components/button.js +39 -0
  73. package/dist/esm/components/calendar.js +70 -0
  74. package/dist/esm/components/card.js +18 -0
  75. package/dist/esm/components/chart.js +135 -0
  76. package/dist/esm/components/checkbox.js +8 -0
  77. package/dist/esm/components/chip.js +22 -0
  78. package/dist/esm/components/collapsible.js +5 -0
  79. package/dist/esm/components/command.js +29 -0
  80. package/dist/esm/components/context-menu.js +33 -0
  81. package/dist/esm/components/country-select.js +118 -0
  82. package/dist/esm/components/date-picker.js +23 -0
  83. package/dist/esm/components/date-range-picker.js +23 -0
  84. package/dist/esm/components/date-time-picker.js +70 -0
  85. package/dist/esm/components/dialog.js +24 -0
  86. package/dist/esm/components/drawer.js +23 -0
  87. package/dist/esm/components/dropdown-menu.js +35 -0
  88. package/dist/esm/components/empty.js +6 -0
  89. package/dist/esm/components/file-preview.js +69 -0
  90. package/dist/esm/components/form.js +63 -0
  91. package/dist/esm/components/inline-edit.js +47 -0
  92. package/dist/esm/components/input-group.js +63 -0
  93. package/dist/esm/components/input-otp.js +19 -0
  94. package/dist/esm/components/input.js +21 -0
  95. package/dist/esm/components/label.js +9 -0
  96. package/dist/esm/components/menubar.js +45 -0
  97. package/dist/esm/components/navigation-menu.js +24 -0
  98. package/dist/esm/components/pagination.js +23 -0
  99. package/dist/esm/components/phone-input.js +181 -0
  100. package/dist/esm/components/popover.js +10 -0
  101. package/dist/esm/components/progress.js +7 -0
  102. package/dist/esm/components/radio-button-group.js +47 -0
  103. package/dist/esm/components/radio-group.js +13 -0
  104. package/dist/esm/components/resizable.js +9 -0
  105. package/dist/esm/components/rich-text-editor.js +145 -0
  106. package/dist/esm/components/route.js +11 -0
  107. package/dist/esm/components/scroll-area.js +11 -0
  108. package/dist/esm/components/select.js +26 -0
  109. package/dist/esm/components/separator.js +7 -0
  110. package/dist/esm/components/sheet.js +197 -0
  111. package/dist/esm/components/skeleton.js +6 -0
  112. package/dist/esm/components/slider.js +11 -0
  113. package/dist/esm/components/sonner.js +22 -0
  114. package/dist/esm/components/spinner.js +21 -0
  115. package/dist/esm/components/stepper.js +57 -0
  116. package/dist/esm/components/steps.js +80 -0
  117. package/dist/esm/components/switch.js +30 -0
  118. package/dist/esm/components/table.js +22 -0
  119. package/dist/esm/components/tabs.js +12 -0
  120. package/dist/esm/components/textarea.js +8 -0
  121. package/dist/esm/components/time-picker.js +74 -0
  122. package/dist/esm/components/toast.js +33 -0
  123. package/dist/esm/components/toaster.js +9 -0
  124. package/dist/esm/components/toggle-group.js +21 -0
  125. package/dist/esm/components/toggle.js +25 -0
  126. package/dist/esm/components/tooltip.js +10 -0
  127. package/dist/esm/hooks/use-toast.js +128 -0
  128. package/dist/esm/index.js +67 -0
  129. package/dist/esm/lib/countryUtils.js +87 -0
  130. package/dist/esm/lib/utils.js +5 -0
  131. package/dist/styles.css +152 -0
  132. package/dist/types/components/accordion.d.ts +11 -0
  133. package/dist/types/components/alert.d.ts +12 -0
  134. package/dist/types/components/aspect-ratio.d.ts +3 -0
  135. package/dist/types/components/avatar.d.ts +19 -0
  136. package/dist/types/components/badge.d.ts +9 -0
  137. package/dist/types/components/breadcrumb.d.ts +19 -0
  138. package/dist/types/components/button.d.ts +14 -0
  139. package/dist/types/components/calendar.d.ts +7 -0
  140. package/dist/types/components/card.d.ts +11 -0
  141. package/dist/types/components/chart.d.ts +66 -0
  142. package/dist/types/components/checkbox.d.ts +4 -0
  143. package/dist/types/components/chip.d.ts +10 -0
  144. package/dist/types/components/collapsible.d.ts +5 -0
  145. package/dist/types/components/command.d.ts +80 -0
  146. package/dist/types/components/context-menu.d.ts +27 -0
  147. package/dist/types/components/country-select.d.ts +17 -0
  148. package/dist/types/components/date-picker.d.ts +9 -0
  149. package/dist/types/components/date-range-picker.d.ts +10 -0
  150. package/dist/types/components/date-time-picker.d.ts +10 -0
  151. package/dist/types/components/dialog.d.ts +23 -0
  152. package/dist/types/components/drawer.d.ts +22 -0
  153. package/dist/types/components/dropdown-menu.d.ts +27 -0
  154. package/dist/types/components/empty.d.ts +6 -0
  155. package/dist/types/components/file-preview.d.ts +9 -0
  156. package/dist/types/components/form.d.ts +23 -0
  157. package/dist/types/components/inline-edit.d.ts +10 -0
  158. package/dist/types/components/input-group.d.ts +16 -0
  159. package/dist/types/components/input-otp.d.ts +34 -0
  160. package/dist/types/components/input.d.ts +9 -0
  161. package/dist/types/components/label.d.ts +5 -0
  162. package/dist/types/components/menubar.d.ts +28 -0
  163. package/dist/types/components/navigation-menu.d.ts +12 -0
  164. package/dist/types/components/pagination.d.ts +29 -0
  165. package/dist/types/components/phone-input.d.ts +20 -0
  166. package/dist/types/components/popover.d.ts +9 -0
  167. package/dist/types/components/progress.d.ts +4 -0
  168. package/dist/types/components/radio-button-group.d.ts +17 -0
  169. package/dist/types/components/radio-group.d.ts +5 -0
  170. package/dist/types/components/resizable.d.ts +23 -0
  171. package/dist/types/components/rich-text-editor.d.ts +8 -0
  172. package/dist/types/components/route.d.ts +10 -0
  173. package/dist/types/components/scroll-area.d.ts +5 -0
  174. package/dist/types/components/select.d.ts +13 -0
  175. package/dist/types/components/separator.d.ts +4 -0
  176. package/dist/types/components/sheet.d.ts +49 -0
  177. package/dist/types/components/skeleton.d.ts +2 -0
  178. package/dist/types/components/slider.d.ts +4 -0
  179. package/dist/types/components/sonner.d.ts +4 -0
  180. package/dist/types/components/spinner.d.ts +8 -0
  181. package/dist/types/components/stepper.d.ts +17 -0
  182. package/dist/types/components/steps.d.ts +64 -0
  183. package/dist/types/components/switch.d.ts +10 -0
  184. package/dist/types/components/table.d.ts +14 -0
  185. package/dist/types/components/tabs.d.ts +7 -0
  186. package/dist/types/components/textarea.d.ts +3 -0
  187. package/dist/types/components/time-picker.d.ts +10 -0
  188. package/dist/types/components/toast.d.ts +15 -0
  189. package/dist/types/components/toaster.d.ts +1 -0
  190. package/dist/types/components/toggle-group.d.ts +12 -0
  191. package/dist/types/components/toggle.d.ts +12 -0
  192. package/dist/types/components/tooltip.d.ts +7 -0
  193. package/dist/types/hooks/use-toast.d.ts +44 -0
  194. package/dist/types/index.d.ts +62 -0
  195. package/dist/types/lib/countryUtils.d.ts +20 -0
  196. package/dist/types/lib/utils.d.ts +2 -0
  197. package/package.json +84 -0
  198. package/tailwind-preset.js +70 -0
@@ -0,0 +1,145 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { cn } from '../lib/utils';
4
+ import BulletList from '@tiptap/extension-bullet-list';
5
+ import ListItem from '@tiptap/extension-list-item';
6
+ import OrderedList from '@tiptap/extension-ordered-list';
7
+ import Link from '@tiptap/extension-link';
8
+ import UnderlineExtension from '@tiptap/extension-underline';
9
+ import Placeholder from '@tiptap/extension-placeholder';
10
+ import { EditorContent, useEditor } from '@tiptap/react';
11
+ import StarterKit from '@tiptap/starter-kit';
12
+ import { Plugin, PluginKey } from '@tiptap/pm/state';
13
+ import { Bold, Italic, Link as LinkIcon, List, ListOrdered, Underline, } from 'lucide-react';
14
+ import { useState } from 'react';
15
+ import { Input } from './input';
16
+ import { Button } from './button';
17
+ import { Popover, PopoverContent, PopoverTrigger } from './popover';
18
+ // Custom Link extension to prevent clicks
19
+ const createCustomLink = (onLinkClick) => {
20
+ return Link.extend({
21
+ addProseMirrorPlugins() {
22
+ return [
23
+ new Plugin({
24
+ key: new PluginKey('handleLinkClick'),
25
+ props: {
26
+ handleClick(_view, _pos, event) {
27
+ const link = event.target?.closest('a');
28
+ if (link) {
29
+ event.preventDefault();
30
+ event.stopPropagation();
31
+ const href = link.getAttribute('href');
32
+ if (href) {
33
+ onLinkClick(href);
34
+ }
35
+ return true;
36
+ }
37
+ return false;
38
+ },
39
+ },
40
+ }),
41
+ ];
42
+ },
43
+ }).configure({
44
+ openOnClick: false,
45
+ HTMLAttributes: {
46
+ class: 'text-primary underline cursor-pointer',
47
+ rel: 'noopener noreferrer nofollow',
48
+ },
49
+ });
50
+ };
51
+ const MenuBar = ({ editor, linkUrl, setLinkUrl, linkPopoverOpen, setLinkPopoverOpen, isEditingExistingLink, setIsEditingExistingLink, handleSetLink, handleRemoveLink, }) => {
52
+ if (!editor)
53
+ return null;
54
+ return (_jsxs("div", { className: "flex items-center gap-fds-xs border-b border-border bg-fds-gray-10 px-fds-md py-fds-md dark:bg-card", children: [_jsx("button", { onClick: () => editor.chain().focus().toggleBold().run(), type: "button", className: "cursor-pointer rounded p-1 hover:bg-fds-gray-20 dark:hover:bg-fds-gray-80", children: _jsx(Bold, { className: cn('h-4 w-4 text-foreground', editor.isActive('bold') && 'text-primary') }) }), _jsx("button", { onClick: () => editor.chain().focus().toggleItalic().run(), type: "button", className: "cursor-pointer rounded p-1 hover:bg-fds-gray-20 dark:hover:bg-fds-gray-80", children: _jsx(Italic, { className: cn('h-4 w-4 text-foreground', editor.isActive('italic') && 'text-primary') }) }), _jsx("button", { onClick: () => editor.chain().focus().toggleUnderline().run(), type: "button", className: "cursor-pointer rounded p-1 hover:bg-fds-gray-20 dark:hover:bg-fds-gray-80", children: _jsx(Underline, { className: cn('h-4 w-4 text-foreground', editor.isActive('underline') && 'text-primary') }) }), _jsx("div", { className: "mx-fds-xs h-4 w-px bg-fds-gray-20 dark:bg-fds-gray-80" }), _jsx("button", { onClick: (e) => {
55
+ e.preventDefault();
56
+ editor.chain().focus().toggleBulletList().run();
57
+ }, type: "button", className: "cursor-pointer rounded p-1 hover:bg-fds-gray-20 dark:hover:bg-fds-gray-80", children: _jsx(List, { className: cn('h-4 w-4 text-foreground', editor.isActive('bulletList') && 'text-primary') }) }), _jsx("button", { onClick: (e) => {
58
+ e.preventDefault();
59
+ editor.chain().focus().toggleOrderedList().run();
60
+ }, type: "button", className: "cursor-pointer rounded p-1 hover:bg-fds-gray-20 dark:hover:bg-fds-gray-80", children: _jsx(ListOrdered, { className: cn('h-4 w-4 text-foreground', editor.isActive('orderedList') && 'text-primary') }) }), _jsxs(Popover, { open: linkPopoverOpen, onOpenChange: setLinkPopoverOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "cursor-pointer rounded p-1 hover:bg-fds-gray-20 dark:hover:bg-fds-gray-80", onClick: () => {
61
+ if (editor.isActive('link')) {
62
+ setLinkUrl(editor.getAttributes('link').href);
63
+ }
64
+ }, children: _jsx(LinkIcon, { className: cn('h-4 w-4 text-foreground', editor.isActive('link') && 'text-primary') }) }) }), _jsx(PopoverContent, { className: "w-[300px]", children: _jsx("div", { className: "flex flex-col gap-fds-sm", children: isEditingExistingLink ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-fds-sm font-fds-semibold", children: "Visit URL:" }), _jsx("a", { href: linkUrl, target: "_blank", rel: "noopener noreferrer", className: "truncate text-fds-sm text-primary hover:underline", children: linkUrl }), _jsxs("div", { className: "flex gap-fds-xs", children: [_jsx(Button, { size: "small", onClick: () => {
65
+ setIsEditingExistingLink(false);
66
+ }, className: "flex-1", children: "Edit" }), _jsx(Button, { size: "small", type: "text", onClick: handleRemoveLink, className: "flex-1", children: "Remove" })] })] })) : editor.isActive('link') ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-fds-sm font-fds-semibold", children: "Edit Link" }), _jsx(Input, { value: linkUrl, onChange: (e) => setLinkUrl(e.target.value), placeholder: "Enter URL", onKeyDown: (e) => {
67
+ if (e.key === 'Enter') {
68
+ e.preventDefault();
69
+ handleSetLink();
70
+ }
71
+ }, autoFocus: true }), _jsxs("div", { className: "flex gap-fds-xs", children: [_jsx(Button, { size: "small", onClick: handleSetLink, className: "flex-1", children: "Update" }), _jsx(Button, { size: "small", type: "text", onClick: handleRemoveLink, className: "flex-1", children: "Remove" })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-fds-sm font-fds-semibold", children: "Add Link" }), _jsx(Input, { value: linkUrl, onChange: (e) => setLinkUrl(e.target.value), placeholder: "Enter URL", onKeyDown: (e) => {
72
+ if (e.key === 'Enter') {
73
+ e.preventDefault();
74
+ handleSetLink();
75
+ }
76
+ }, autoFocus: true }), _jsx(Button, { size: "small", onClick: handleSetLink, children: "Add Link" })] })) }) })] })] }));
77
+ };
78
+ export const RichTextEditor = ({ value = '', onChange, placeholder = 'Type your message...', className, }) => {
79
+ const [linkPopoverOpen, setLinkPopoverOpen] = useState(false);
80
+ const [linkUrl, setLinkUrl] = useState('');
81
+ const [isEditingExistingLink, setIsEditingExistingLink] = useState(false);
82
+ const handleLinkClick = (href) => {
83
+ setLinkUrl(href);
84
+ setIsEditingExistingLink(true);
85
+ setLinkPopoverOpen(true);
86
+ };
87
+ const CustomLink = createCustomLink(handleLinkClick);
88
+ const editor = useEditor({
89
+ immediatelyRender: false,
90
+ extensions: [
91
+ StarterKit.configure({
92
+ bulletList: false,
93
+ orderedList: false,
94
+ listItem: false,
95
+ }),
96
+ ListItem,
97
+ BulletList.configure({
98
+ HTMLAttributes: {
99
+ class: 'list-disc list-outside ml-4',
100
+ },
101
+ }),
102
+ OrderedList.configure({
103
+ HTMLAttributes: {
104
+ class: 'list-decimal list-outside ml-4',
105
+ },
106
+ }),
107
+ UnderlineExtension,
108
+ CustomLink,
109
+ Placeholder.configure({
110
+ placeholder,
111
+ }),
112
+ ],
113
+ content: value,
114
+ onUpdate: ({ editor }) => {
115
+ onChange?.(editor.getHTML());
116
+ },
117
+ editorProps: {
118
+ attributes: {
119
+ class: cn('prose prose-sm focus:outline-none min-h-[80px] px-fds-lg py-fds-sm prose-p:my-1 prose-ul:my-1 prose-ol:my-1 text-fds-sm bg-white dark:bg-black dark:text-white', className),
120
+ },
121
+ },
122
+ });
123
+ const handleSetLink = () => {
124
+ if (linkUrl && editor) {
125
+ // Ensure URL has protocol
126
+ let formattedUrl = linkUrl;
127
+ if (!/^https?:\/\//i.test(linkUrl)) {
128
+ formattedUrl = `https://${linkUrl}`;
129
+ }
130
+ editor.chain().focus().setLink({ href: formattedUrl }).run();
131
+ setLinkUrl('');
132
+ setIsEditingExistingLink(false);
133
+ setLinkPopoverOpen(false);
134
+ }
135
+ };
136
+ const handleRemoveLink = () => {
137
+ if (editor) {
138
+ editor.chain().focus().unsetLink().run();
139
+ setLinkUrl('');
140
+ setIsEditingExistingLink(false);
141
+ setLinkPopoverOpen(false);
142
+ }
143
+ };
144
+ return (_jsxs("div", { className: "w-full", children: [_jsx(MenuBar, { editor: editor, linkUrl: linkUrl, setLinkUrl: setLinkUrl, linkPopoverOpen: linkPopoverOpen, setLinkPopoverOpen: setLinkPopoverOpen, isEditingExistingLink: isEditingExistingLink, setIsEditingExistingLink: setIsEditingExistingLink, handleSetLink: handleSetLink, handleRemoveLink: handleRemoveLink }), _jsx(EditorContent, { editor: editor, placeholder: placeholder })] }));
145
+ };
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from '../lib/utils';
4
+ const Route = React.forwardRef(({ className, type = 'point-to-point', start, end, ...props }, ref) => {
5
+ if (type === 'point-to-point') {
6
+ return (_jsxs("div", { ref: ref, className: cn('flex items-center gap-fds-sm', className), ...props, children: [start, _jsxs("div", { className: "relative flex items-center", children: [_jsx("div", { className: "h-[5px] w-[5px] rounded-full bg-foreground" }), _jsx("div", { className: "h-px w-[22px] bg-foreground" }), _jsx("div", { className: "h-[5px] w-[5px] rounded-full bg-foreground" })] }), end] }));
7
+ }
8
+ return null;
9
+ });
10
+ Route.displayName = 'Route';
11
+ export { Route };
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
4
+ import { cn } from "../lib/utils";
5
+ const ScrollArea = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(ScrollAreaPrimitive.Root, { ref: ref, className: cn("relative overflow-hidden", className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children: children }), _jsx(ScrollBar, {}), _jsx(ScrollAreaPrimitive.Corner, {})] })));
6
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
7
+ const ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...props }, ref) => (_jsx(ScrollAreaPrimitive.ScrollAreaScrollbar, { ref: ref, orientation: orientation, className: cn("flex touch-none select-none transition-colors", orientation === "vertical" &&
8
+ "h-full w-2.5 border-l border-l-transparent p-[1px]", orientation === "horizontal" &&
9
+ "h-2.5 flex-col border-t border-t-transparent p-[1px]", className), ...props, children: _jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" }) })));
10
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
11
+ export { ScrollArea, ScrollBar };
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import * as SelectPrimitive from '@radix-ui/react-select';
4
+ import { cn } from '../lib/utils';
5
+ import { IconCaretDown, IconCaretUp } from '@freightos/icons';
6
+ const Select = SelectPrimitive.Root;
7
+ const SelectGroup = SelectPrimitive.Group;
8
+ const SelectValue = SelectPrimitive.Value;
9
+ const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn('flex h-[32px] w-full items-center justify-between rounded-fds-md border border-input-border bg-input py-2 pl-3 pr-2 text-sm transition-[color,box-shadow] focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[state=open]:border-[#2075bd] data-[placeholder]:text-muted-foreground data-[state=open]:shadow-[0_0_0_2px_var(--fds-color-primary-blue-20)] [&>span]:line-clamp-1 [&[data-state=open]>span[data-radix-select-icon]>svg]:rotate-180', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(IconCaretDown, { className: "transition-transform duration-200" }) })] })));
10
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
11
+ const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollUpButton, { ref: ref, className: cn('flex cursor-default items-center justify-center py-1', className), ...props, children: _jsx(IconCaretUp, {}) })));
12
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
13
+ const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollDownButton, { ref: ref, className: cn('flex cursor-default items-center justify-center py-1', className), ...props, children: _jsx(IconCaretDown, {}) })));
14
+ SelectScrollDownButton.displayName =
15
+ SelectPrimitive.ScrollDownButton.displayName;
16
+ const SelectContent = React.forwardRef(({ className, children, position = 'popper', ...props }, ref) => (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { ref: ref, className: cn('relative z-[9999] max-h-[--radix-select-content-available-height] min-w-[8rem] w-max origin-[--radix-select-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-fds-md bg-popover text-popover-foreground shadow-fds-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', position === 'popper' &&
17
+ 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', className), position: position, ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { className: cn('w-full', position === 'popper' &&
18
+ 'h-[var(--radix-select-trigger-height)] min-w-[var(--radix-select-trigger-width)]'), children: children }), _jsx(SelectScrollDownButton, {})] }) })));
19
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
20
+ const SelectLabel = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Label, { ref: ref, className: cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className), ...props })));
21
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
22
+ const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => (_jsx(SelectPrimitive.Item, { ref: ref, className: cn('relative flex w-full cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[disabled]:opacity-50', className), ...props, children: _jsx(SelectPrimitive.ItemText, { asChild: true, children: _jsx("div", { className: "flex w-full flex-1 items-center", children: children }) }) })));
23
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
24
+ const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Separator, { ref: ref, className: cn('-mx-1 my-1 h-px bg-muted', className), ...props })));
25
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
26
+ export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, };
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
3
+ import * as React from 'react';
4
+ import { cn } from '../lib/utils';
5
+ const Separator = React.forwardRef(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (_jsx(SeparatorPrimitive.Root, { ref: ref, decorative: decorative, orientation: orientation, className: cn('shrink-0 bg-fds-gray-20', orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]', className), ...props })));
6
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
7
+ export { Separator };
@@ -0,0 +1,197 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import * as SheetPrimitive from '@radix-ui/react-dialog';
5
+ import { cva } from 'class-variance-authority';
6
+ import { X } from 'lucide-react';
7
+ import { cn } from '../lib/utils';
8
+ const SheetContext = React.createContext({
9
+ level: 0,
10
+ parentSheetWidth: undefined,
11
+ registerNestedSheet: () => { },
12
+ unregisterNestedSheet: () => { },
13
+ hasNestedSheetOpen: false,
14
+ nestedSheetWidth: undefined,
15
+ });
16
+ export const useSheetContext = () => React.useContext(SheetContext);
17
+ // Sheet wrapper that provides context
18
+ const SheetProvider = ({ children, width }) => {
19
+ const parentContext = useSheetContext();
20
+ const [nestedSheetCount, setNestedSheetCount] = React.useState(0);
21
+ const registerNestedSheet = React.useCallback(() => {
22
+ setNestedSheetCount((count) => count + 1);
23
+ }, []);
24
+ const unregisterNestedSheet = React.useCallback(() => {
25
+ setNestedSheetCount((count) => Math.max(0, count - 1));
26
+ }, []);
27
+ const contextValue = React.useMemo(() => ({
28
+ level: parentContext.level + 1,
29
+ parentSheetWidth: width,
30
+ registerNestedSheet,
31
+ unregisterNestedSheet,
32
+ hasNestedSheetOpen: nestedSheetCount > 0,
33
+ }), [
34
+ parentContext.level,
35
+ width,
36
+ registerNestedSheet,
37
+ unregisterNestedSheet,
38
+ nestedSheetCount,
39
+ ]);
40
+ return (_jsx(SheetContext.Provider, { value: contextValue, children: children }));
41
+ };
42
+ const SheetRoot = ({ open, width, ...props }) => {
43
+ const parentContext = useSheetContext();
44
+ // Register/unregister when open state changes
45
+ React.useEffect(() => {
46
+ if (open && parentContext.level > 0) {
47
+ parentContext.registerNestedSheet(width);
48
+ return () => {
49
+ parentContext.unregisterNestedSheet();
50
+ };
51
+ }
52
+ return undefined;
53
+ }, [open, parentContext, width]);
54
+ return _jsx(SheetPrimitive.Root, { open: open, ...props });
55
+ };
56
+ const Sheet = SheetRoot;
57
+ const SheetTrigger = SheetPrimitive.Trigger;
58
+ const SheetClose = SheetPrimitive.Close;
59
+ const SheetPortal = SheetPrimitive.Portal;
60
+ const SheetOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(SheetPrimitive.Overlay, { className: cn('fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', className), ...props, ref: ref })));
61
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
62
+ const sheetVariants = cva('fixed bg-background shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out bg-card flex flex-col', {
63
+ variants: {
64
+ side: {
65
+ top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
66
+ bottom: 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
67
+ left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
68
+ right: 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
69
+ },
70
+ zIndex: {
71
+ default: 'z-50',
72
+ high: 'z-[1100]',
73
+ pushed: 'z-[1150]', // Between high (1100) and nested overlay (1199)
74
+ nested: 'z-[1200]',
75
+ },
76
+ },
77
+ defaultVariants: {
78
+ side: 'right',
79
+ zIndex: 'default',
80
+ },
81
+ });
82
+ const SheetContent = React.forwardRef(({ side = 'right', zIndex = 'default', className, overlayClassName, hideCloseButton = false, sheetWidth, children, ...props }, ref) => {
83
+ // Read the parent context BEFORE potentially wrapping with SheetProvider
84
+ const parentContext = useSheetContext();
85
+ // Track nested sheets for THIS sheet using local state
86
+ const [localNestedSheetCount, setLocalNestedSheetCount] = React.useState(0);
87
+ const [localNestedSheetWidth, setLocalNestedSheetWidth] = React.useState();
88
+ const closeTimeoutRef = React.useRef(null);
89
+ const registerLocalNestedSheet = React.useCallback((width) => {
90
+ // Clear any pending close timeout when opening a new nested sheet
91
+ if (closeTimeoutRef.current) {
92
+ clearTimeout(closeTimeoutRef.current);
93
+ closeTimeoutRef.current = null;
94
+ }
95
+ setLocalNestedSheetCount((count) => count + 1);
96
+ if (width) {
97
+ setLocalNestedSheetWidth(width);
98
+ }
99
+ }, []);
100
+ const unregisterLocalNestedSheet = React.useCallback(() => {
101
+ setLocalNestedSheetCount((count) => Math.max(0, count - 1));
102
+ setLocalNestedSheetWidth(undefined);
103
+ // Clear any existing timeout
104
+ if (closeTimeoutRef.current) {
105
+ clearTimeout(closeTimeoutRef.current);
106
+ closeTimeoutRef.current = null;
107
+ }
108
+ }, []);
109
+ // Cleanup timeout on unmount
110
+ React.useEffect(() => {
111
+ return () => {
112
+ if (closeTimeoutRef.current) {
113
+ clearTimeout(closeTimeoutRef.current);
114
+ }
115
+ };
116
+ }, []);
117
+ // This sheet should be pushed if IT has nested sheets open
118
+ const shouldBePushed = localNestedSheetCount > 0 && sheetWidth;
119
+ // Create a custom context value that uses THIS sheet's local nested sheet tracking
120
+ const customContextValue = React.useMemo(() => ({
121
+ level: parentContext.level + 1,
122
+ parentSheetWidth: sheetWidth,
123
+ registerNestedSheet: registerLocalNestedSheet,
124
+ unregisterNestedSheet: unregisterLocalNestedSheet,
125
+ hasNestedSheetOpen: localNestedSheetCount > 0,
126
+ nestedSheetWidth: localNestedSheetWidth,
127
+ }), [
128
+ parentContext.level,
129
+ sheetWidth,
130
+ registerLocalNestedSheet,
131
+ unregisterLocalNestedSheet,
132
+ localNestedSheetCount,
133
+ localNestedSheetWidth,
134
+ ]);
135
+ // Wrap children with context provider if sheetWidth is provided
136
+ const wrappedChildren = sheetWidth ? (_jsx(SheetContext.Provider, { value: customContextValue, children: children })) : (children);
137
+ // Determine z-index based on nesting level AND pushed state
138
+ // A sheet is nested if its parent level >= 1 (meaning it's inside another sheet)
139
+ let effectiveZIndex = parentContext.level >= 1 ? 'nested' : zIndex;
140
+ const isNestedSheet = parentContext.level >= 1;
141
+ // When pushed, keep the same z-index (it will be under nested sheet's overlay anyway)
142
+ // Don't change z-index when pushed - the nested overlay (z-1199) will be above this (z-1100)
143
+ // Calculate overlay z-index
144
+ const overlayZIndex = effectiveZIndex === 'nested'
145
+ ? 1199
146
+ : effectiveZIndex === 'high'
147
+ ? 1099
148
+ : 50;
149
+ // Animation timing classes
150
+ const animationClasses = 'data-[state=closed]:duration-300 data-[state=open]:duration-500';
151
+ // Calculate transform for pushed state
152
+ // Strategy: During close, parent slides back at same speed as nested slides out
153
+ // Both travel in the positive direction (to the right) so they stick together
154
+ const transformStyle = shouldBePushed && localNestedSheetWidth
155
+ ? {
156
+ // Opening: animate to pushed position (move left)
157
+ transform: `translate3d(-${localNestedSheetWidth}, 0, 0)`,
158
+ transition: 'transform 500ms linear',
159
+ }
160
+ : {
161
+ // Closing: animate back to center (move right)
162
+ transform: 'translate3d(0, 0, 0)',
163
+ transition: 'transform 300ms linear',
164
+ };
165
+ const inlineStyle = {
166
+ ...transformStyle,
167
+ // Force GPU acceleration for both sheets to ensure smooth, synchronized animations
168
+ willChange: 'transform',
169
+ // For nested sheets, override animation timing to linear
170
+ ...(isNestedSheet && {
171
+ animationTimingFunction: 'linear',
172
+ }),
173
+ };
174
+ // Debug logging
175
+ // console.log('📊 Sheet render:', {
176
+ // level: parentContext.level,
177
+ // hasNestedSheetOpen: parentContext.hasNestedSheetOpen,
178
+ // parentSheetWidth: parentContext.parentSheetWidth,
179
+ // shouldBePushed,
180
+ // effectiveZIndex,
181
+ // overlayZIndex,
182
+ // sheetWidth,
183
+ // });
184
+ return (_jsxs(SheetPortal, { children: [!shouldBePushed && !localNestedSheetWidth && (_jsx(SheetOverlay, { className: overlayClassName, style: { zIndex: overlayZIndex } })), _jsxs(SheetPrimitive.Content, { ref: ref, className: cn(sheetVariants({ side, zIndex: effectiveZIndex }), animationClasses, shouldBePushed && 'pointer-events-none', className), style: inlineStyle, ...props, children: [wrappedChildren, !hideCloseButton && (_jsxs(SheetPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary", children: [_jsx(X, { className: "h-4 w-4" }), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
185
+ });
186
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
187
+ const SheetHeader = ({ className, ...props }) => (_jsx("div", { className: cn('flex flex-shrink-0 flex-col space-y-2 px-fds-xl py-fds-xl', className), ...props }));
188
+ SheetHeader.displayName = 'SheetHeader';
189
+ const SheetBody = ({ className, ...props }) => (_jsx("div", { className: cn('flex-1 overflow-y-auto px-fds-xl', className), ...props }));
190
+ SheetBody.displayName = 'SheetBody';
191
+ const SheetFooter = ({ className, ...props }) => (_jsx("div", { className: cn('flex-shrink-0 border-t border-fds-gray-20 px-fds-xl py-fds-xl', className), ...props }));
192
+ SheetFooter.displayName = 'SheetFooter';
193
+ const SheetTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(SheetPrimitive.Title, { ref: ref, className: cn('text-fds-h3 font-fds-bold', className), ...props })));
194
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
195
+ const SheetDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx(SheetPrimitive.Description, { ref: ref, className: cn('text-sm text-muted-foreground', className), ...props })));
196
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
197
+ export { Sheet, SheetProvider, SheetPortal, SheetOverlay, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetBody, SheetFooter, SheetTitle, SheetDescription, };
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils";
3
+ function Skeleton({ className, ...props }) {
4
+ return (_jsx("div", { className: cn("animate-pulse rounded-md bg-muted", className), ...props }));
5
+ }
6
+ export { Skeleton };
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../lib/utils';
3
+ import * as SliderPrimitive from '@radix-ui/react-slider';
4
+ import * as React from 'react';
5
+ const Slider = React.forwardRef(({ className, ...props }, ref) => {
6
+ const value = props.value || props.defaultValue || [0];
7
+ const thumbCount = Array.isArray(value) ? value.length : 1;
8
+ return (_jsxs(SliderPrimitive.Root, { ref: ref, className: cn('relative flex w-full touch-none select-none items-center', className), ...props, children: [_jsx(SliderPrimitive.Track, { className: "relative h-1 w-full grow overflow-hidden rounded-full bg-fds-gray-20", children: _jsx(SliderPrimitive.Range, { className: "absolute h-full bg-fds-blue" }) }), Array.from({ length: thumbCount }).map((_, i) => (_jsx(SliderPrimitive.Thumb, { className: "block h-4 w-4 rounded-full border-2 border-fds-blue bg-fds-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fds-blue-20 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" }, i)))] }));
9
+ });
10
+ Slider.displayName = SliderPrimitive.Root.displayName;
11
+ export { Slider };
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CircleCheck, Info, LoaderCircle, OctagonX, TriangleAlert, } from "lucide-react";
3
+ import { useTheme } from "next-themes";
4
+ import { Toaster as Sonner } from "sonner";
5
+ const Toaster = ({ ...props }) => {
6
+ const { theme = "system" } = useTheme();
7
+ return (_jsx(Sonner, { theme: theme, className: "toaster group", icons: {
8
+ success: _jsx(CircleCheck, { className: "h-4 w-4" }),
9
+ info: _jsx(Info, { className: "h-4 w-4" }),
10
+ warning: _jsx(TriangleAlert, { className: "h-4 w-4" }),
11
+ error: _jsx(OctagonX, { className: "h-4 w-4" }),
12
+ loading: _jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }),
13
+ }, toastOptions: {
14
+ classNames: {
15
+ toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
16
+ description: "group-[.toast]:text-muted-foreground",
17
+ actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
18
+ cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
19
+ },
20
+ }, ...props }));
21
+ };
22
+ export { Toaster };
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { IconLoading } from '@freightos/icons';
3
+ import { cn } from '../lib/utils';
4
+ import { cva } from 'class-variance-authority';
5
+ const spinnerVariants = cva('text-[var(--fds-color-primary-blue)] animate-spin inline-flex items-center justify-center align-middle', {
6
+ variants: {
7
+ size: {
8
+ tiny: 'size-3', // 12px
9
+ small: 'size-4', // 16px
10
+ medium: 'size-6', // 24px
11
+ large: 'size-8', // 32px
12
+ },
13
+ },
14
+ defaultVariants: {
15
+ size: 'medium',
16
+ },
17
+ });
18
+ function Spinner({ className, size, ...props }) {
19
+ return (_jsx("span", { role: "status", "aria-label": "Loading", className: cn(spinnerVariants({ size, className })), ...props, children: _jsx(IconLoading, { className: "w-full h-full" }) }));
20
+ }
21
+ export { Spinner, spinnerVariants };
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/utils";
5
+ const StepperContext = React.createContext(null);
6
+ const useStepper = () => {
7
+ const context = React.useContext(StepperContext);
8
+ if (!context) {
9
+ throw new Error("Stepper components must be used within a Stepper");
10
+ }
11
+ return context;
12
+ };
13
+ const Stepper = React.forwardRef(({ className, defaultValue = 1, value, orientation = "horizontal", children, ...props }, ref) => {
14
+ const currentValue = value ?? defaultValue;
15
+ return (_jsx(StepperContext.Provider, { value: { value: currentValue, orientation }, children: _jsx("div", { ref: ref, "data-orientation": orientation, className: cn("group/stepper flex w-full", orientation === "horizontal" ? "flex-row items-start" : "flex-col", className), ...props, children: children }) }));
16
+ });
17
+ Stepper.displayName = "Stepper";
18
+ const StepperItemContext = React.createContext(null);
19
+ const useStepperItem = () => {
20
+ const context = React.useContext(StepperItemContext);
21
+ if (!context) {
22
+ throw new Error("StepperItem components must be used within a StepperItem");
23
+ }
24
+ return context;
25
+ };
26
+ const StepperItem = React.forwardRef(({ className, step, children, ...props }, ref) => {
27
+ const { value } = useStepper();
28
+ const isActive = step === value;
29
+ const isCompleted = step < value;
30
+ return (_jsx(StepperItemContext.Provider, { value: { step, isActive, isCompleted }, children: _jsx("div", { ref: ref, "data-state": isActive ? "active" : isCompleted ? "completed" : "inactive", className: cn("relative flex items-center", className), ...props, children: children }) }));
31
+ });
32
+ StepperItem.displayName = "StepperItem";
33
+ const StepperTrigger = React.forwardRef(({ className, children, ...props }, ref) => {
34
+ return (_jsx("div", { ref: ref, className: cn("flex items-center gap-2", className), ...props, children: children }));
35
+ });
36
+ StepperTrigger.displayName = "StepperTrigger";
37
+ const StepperIndicator = React.forwardRef(({ className, children, ...props }, ref) => {
38
+ const { isActive, isCompleted, step } = useStepperItem();
39
+ return (_jsx("div", { ref: ref, className: cn("flex shrink-0 items-center justify-center rounded-full text-fds-xs transition-colors relative z-10", "h-[18px] w-[18px] font-fds-extrabold", isCompleted && "bg-fds-blue-20 text-white", isActive && "bg-fds-blue-20 text-white border-[0.5px] border-white shadow-[0_0_0_2px] shadow-fds-blue-20", !isActive && !isCompleted && "bg-fds-gray-10 text-fds-gray-60", className), ...props, children: (isActive || isCompleted) && (children || step) }));
40
+ });
41
+ StepperIndicator.displayName = "StepperIndicator";
42
+ const StepperTitle = React.forwardRef(({ className, ...props }, ref) => {
43
+ const { isActive, isCompleted } = useStepperItem();
44
+ return (_jsx("p", { ref: ref, className: cn("!text-fds-xs transition-colors", isActive && "font-fds-semibold text-foreground", isCompleted && "font-fds-regular text-foreground", !isActive && !isCompleted && "text-fds-gray-50", className), ...props }));
45
+ });
46
+ StepperTitle.displayName = "StepperTitle";
47
+ const StepperDescription = React.forwardRef(({ className, ...props }, ref) => {
48
+ return (_jsx("p", { ref: ref, className: cn("text-muted-foreground text-sm", className), ...props }));
49
+ });
50
+ StepperDescription.displayName = "StepperDescription";
51
+ const StepperSeparator = React.forwardRef(({ className, ...props }, ref) => {
52
+ const { orientation } = useStepper();
53
+ const { isCompleted } = useStepperItem();
54
+ return (_jsx("div", { ref: ref, className: cn("shrink-0 transition-colors", isCompleted ? "bg-fds-blue-20" : "bg-fds-gray-10", orientation === "horizontal" ? "h-[2px] w-full" : "h-full w-[2px]", className), ...props }));
55
+ });
56
+ StepperSeparator.displayName = "StepperSeparator";
57
+ export { Stepper, StepperItem, StepperTrigger, StepperIndicator, StepperTitle, StepperDescription, StepperSeparator, };
@@ -0,0 +1,80 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { cn } from '../lib/utils';
4
+ import { IconCaretDown, IconCheck } from '@freightos/icons';
5
+ import { cva } from 'class-variance-authority';
6
+ import * as React from 'react';
7
+ const StepGroupContext = React.createContext({
8
+ isInsideGroup: false,
9
+ });
10
+ const StepsContainer = ({ children, className, }) => {
11
+ return _jsx("div", { className: cn('flex flex-col', className), children: children });
12
+ };
13
+ StepsContainer.displayName = 'StepsContainer';
14
+ const StepGroup = ({ icon, title, children, className, showLineAbove = false, showLineBelow = false, lineAboveCompleted = false, lineBelowCompleted = false, defaultOpen = true, }) => {
15
+ const [isOpen, setIsOpen] = React.useState(defaultOpen);
16
+ const hasChildren = React.Children.count(children) > 0;
17
+ return (_jsx(StepGroupContext.Provider, { value: { isInsideGroup: true }, children: _jsxs("div", { className: cn('flex flex-col', className), children: [showLineAbove && (_jsx("div", { className: "relative flex h-4 gap-fds-md overflow-hidden", children: _jsx("div", { className: "relative flex w-4 flex-shrink-0 justify-center", children: _jsx("div", { className: cn('absolute bottom-0 left-[7px] top-0 w-0 border-l-2', lineAboveCompleted
18
+ ? 'border-fds-blue-20'
19
+ : 'border-fds-gray-10') }) }) })), _jsxs("div", { className: "relative flex items-center gap-fds-md", children: [_jsxs("div", { className: "relative flex w-4 flex-shrink-0 flex-col items-center", children: [_jsx("div", { className: "relative z-10 flex h-6 w-6 items-center justify-center rounded-full bg-fds-blue-10 text-fds-gray-50 ring-4 ring-white dark:ring-transparent", children: icon }), hasChildren && isOpen && (_jsx("div", { className: cn('absolute bottom-[-8px] left-[7px] top-6 w-0 border-l-2', lineBelowCompleted
20
+ ? 'border-fds-blue-20'
21
+ : 'border-fds-gray-10') })), !isOpen && showLineBelow && (_jsx("div", { className: cn('absolute bottom-[-24px] left-[7px] top-6 w-0 border-l-2', lineBelowCompleted
22
+ ? 'border-fds-blue-20'
23
+ : 'border-fds-gray-10') }))] }), _jsxs("button", { type: "button", onClick: () => setIsOpen(!isOpen), className: "flex flex-1 items-center justify-between py-fds-xs", children: [_jsx("span", { className: "text-fds-h6 font-fds-bold", children: title }), hasChildren && (_jsx(IconCaretDown, { size: 18, className: cn('text-fds-gray-50 transition-transform duration-200', isOpen && 'rotate-180') }))] })] }), _jsx("div", { className: cn('grid transition-[grid-template-rows] duration-300 ease-in-out', isOpen ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'), children: _jsx("div", { className: "overflow-hidden", children: children }) })] }) }));
24
+ };
25
+ StepGroup.displayName = 'StepGroup';
26
+ const StepSubGroup = ({ children, label, className, lineColor = 'gray', }) => {
27
+ const borderClass = lineColor === 'blue' ? 'border-fds-blue-20' : 'border-fds-gray-10';
28
+ return (_jsxs("div", { className: cn('relative', className), children: [_jsxs("div", { className: "relative flex gap-fds-md", children: [_jsx("div", { className: "relative w-4 flex-shrink-0", children: _jsx("div", { className: cn('absolute bottom-0 left-[7px] top-0 w-0 border-l-2', borderClass) }) }), _jsx("div", { className: "flex-1 border-t border-dashed border-border" })] }), children, _jsxs("div", { className: "relative flex gap-fds-md", children: [_jsx("div", { className: "relative w-4 flex-shrink-0", children: _jsx("div", { className: cn('absolute bottom-0 left-[7px] top-0 w-0 border-l-2', borderClass) }) }), _jsx("div", { className: "flex-1 border-t border-dashed border-border" })] }), label && (_jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2", children: label }))] }));
29
+ };
30
+ StepSubGroup.displayName = 'StepSubGroup';
31
+ /* -----------------------------------------------------------------------------
32
+ * Step - Individual step item
33
+ * -------------------------------------------------------------------------- */
34
+ const stepIndicatorVariants = cva('flex items-center justify-center rounded-full', {
35
+ variants: {
36
+ status: {
37
+ completed: 'h-[16px] w-[16px] bg-fds-blue text-white',
38
+ active: 'h-[16px] w-[16px] border-2 border-fds-blue bg-white dark:bg-transparent',
39
+ pending: 'h-[16px] w-[16px] border-2 border-dashed border-fds-gray-30 bg-white dark:bg-transparent',
40
+ },
41
+ },
42
+ defaultVariants: {
43
+ status: 'pending',
44
+ },
45
+ });
46
+ const Step = ({ status = 'pending', showLine = true, progressReached = false, nextStepCompleted = false, children, className, meta, }) => {
47
+ const isCompleted = status === 'completed';
48
+ const { isInsideGroup } = React.useContext(StepGroupContext);
49
+ // Visual status: show as completed if progress has reached this step
50
+ const visuallyCompleted = isCompleted || progressReached;
51
+ const visualStatus = visuallyCompleted ? 'completed' : status;
52
+ // Line colors: blue if progress has reached this step or beyond
53
+ const lineAboveColor = visuallyCompleted
54
+ ? 'border-fds-blue-20'
55
+ : 'border-fds-gray-10';
56
+ const lineBelowColor = nextStepCompleted
57
+ ? 'border-fds-blue-20'
58
+ : 'border-fds-gray-10';
59
+ return (_jsxs("div", { className: cn('flex flex-col', className), children: [isInsideGroup && (_jsxs("div", { className: "relative flex h-3 gap-fds-md", children: [_jsx("div", { className: cn('absolute bottom-0 left-[7px] top-0 w-0 border-l-2', lineAboveColor) }), _jsx("div", { className: "w-4 flex-shrink-0" }), _jsx("div", { className: "flex-1" })] })), _jsxs("div", { className: "relative flex items-center gap-fds-md", children: [isInsideGroup && (_jsx("div", { className: cn('absolute bottom-1/2 left-[7px] top-0 w-0 border-l-2', lineAboveColor) })), showLine && (_jsx("div", { className: cn('absolute bottom-0 left-[7px] top-1/2 w-0 border-l-2', lineBelowColor) })), _jsx("div", { className: "relative z-10 flex w-4 flex-shrink-0 justify-center bg-white py-2 dark:bg-transparent", children: visualStatus === 'pending' ? (_jsx("div", { className: "h-[11px] w-[11px] rounded-full border-[1.5px] border-dashed border-fds-gray-30 bg-card" })) : (_jsx("div", { className: stepIndicatorVariants({ status: visualStatus }), children: visuallyCompleted && _jsx(IconCheck, { size: 10 }) })) }), _jsxs("div", { className: "flex flex-1 justify-between", children: [_jsx("div", { className: "flex-1", children: children }), meta && _jsx("div", { className: "ml-fds-sm", children: meta })] })] }), showLine && (_jsxs("div", { className: "relative flex gap-fds-md pb-1", children: [_jsx("div", { className: cn('absolute bottom-0 left-[7px] top-0 w-0 border-l-2', lineBelowColor) }), _jsx("div", { className: "w-4 flex-shrink-0" }), _jsx("div", { className: "flex-1" })] }))] }));
60
+ };
61
+ Step.displayName = 'Step';
62
+ const StepTitle = ({ children, className }) => (_jsx("div", { className: cn('font-fds-semibold', className), children: children }));
63
+ StepTitle.displayName = 'StepTitle';
64
+ const StepDescription = ({ location, estimatedDate, actualDate, children, className, }) => {
65
+ if (children) {
66
+ return _jsx("div", { className: cn('', className), children: children });
67
+ }
68
+ return (_jsxs("div", { className: cn('flex items-center gap-fds-xs', className), children: [location && (_jsxs(_Fragment, { children: [_jsx("span", { className: "font-fds-semibold", children: location }), _jsx("span", { className: "h-[4px] w-[4px] rounded-full bg-fds-gray-20" })] })), actualDate ? (_jsxs(_Fragment, { children: [estimatedDate && (_jsx("span", { className: "line-through", children: estimatedDate })), _jsx("span", { className: "text-fds-red", children: actualDate })] })) : estimatedDate ? (_jsx("span", { children: estimatedDate })) : (_jsx("span", { children: "TBD" }))] }));
69
+ };
70
+ StepDescription.displayName = 'StepDescription';
71
+ const StepMeta = ({ children, className }) => (_jsx("div", { className: cn('flex items-center gap-fds-xs font-fds-semibold text-fds-gray-60', className), children: children }));
72
+ StepMeta.displayName = 'StepMeta';
73
+ /* -----------------------------------------------------------------------------
74
+ * Legacy exports for compatibility
75
+ * -------------------------------------------------------------------------- */
76
+ const Steps = StepsContainer;
77
+ const StepsAccordion = StepsContainer;
78
+ const StepIndicator = () => null; // No longer needed - indicator is built into Step
79
+ const StepContent = ({ children, className }) => _jsx("div", { className: className, children: children });
80
+ export { Step, StepContent, StepDescription, StepGroup, StepIndicator, stepIndicatorVariants, StepMeta, Steps, StepsAccordion, StepsContainer, StepSubGroup, StepTitle, };