@altimateai/ui-components 0.0.29 → 0.0.31-beta.1

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,179 @@
1
+ import { Meta, StoryFn } from "@storybook/react";
2
+ import { DebouncedInput, DebouncedInputProps } from "./DebouncedInput";
3
+ import { useState } from "react";
4
+ import { IconSearch, IconUser, IconMail } from "@tabler/icons-react";
5
+
6
+ export default {
7
+ title: "Shadcn/Components/DebouncedInput",
8
+ component: DebouncedInput,
9
+ argTypes: {
10
+ disabled: {
11
+ control: "boolean",
12
+ },
13
+ type: {
14
+ control: "select",
15
+ options: ["text", "password", "email", "number"],
16
+ },
17
+ iconPosition: {
18
+ control: "select",
19
+ options: ["left", "right"],
20
+ },
21
+ debounceMs: {
22
+ control: "number",
23
+ },
24
+ },
25
+ } as Meta<typeof DebouncedInput>;
26
+
27
+ const Template: StoryFn<DebouncedInputProps> = (args: DebouncedInputProps) => {
28
+ const [debouncedValue, setDebouncedValue] = useState("");
29
+
30
+ return (
31
+ <div className="al-p-4 al-max-w-md al-space-y-4">
32
+ <DebouncedInput
33
+ {...args}
34
+ onChange={newValue => {
35
+ setDebouncedValue(newValue);
36
+ args.onChange?.(newValue);
37
+ }}
38
+ />
39
+ <div className="al-space-y-2 al-text-sm">
40
+ <div>
41
+ <strong>Debounced Value:</strong>{" "}
42
+ <code className="al-bg-gray-100 al-px-1 al-rounded">{debouncedValue || "empty"}</code>
43
+ </div>
44
+ <div>
45
+ <strong>Debounce Delay:</strong>{" "}
46
+ <code className="al-bg-gray-100 al-px-1 al-rounded">{args.debounceMs || 0}ms</code>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ );
51
+ };
52
+
53
+ export const Default = Template.bind({});
54
+ Default.args = {
55
+ placeholder: "Type something...",
56
+ debounceMs: 0,
57
+ };
58
+
59
+ export const WithDebounce300ms = Template.bind({});
60
+ WithDebounce300ms.args = {
61
+ placeholder: "Search with 300ms debounce...",
62
+ debounceMs: 300,
63
+ };
64
+
65
+ export const WithDebounce500ms = Template.bind({});
66
+ WithDebounce500ms.args = {
67
+ placeholder: "Search with 500ms debounce...",
68
+ debounceMs: 500,
69
+ };
70
+
71
+ export const WithDebounce1000ms = Template.bind({});
72
+ WithDebounce1000ms.args = {
73
+ placeholder: "Search with 1000ms debounce...",
74
+ debounceMs: 1000,
75
+ };
76
+
77
+ export const SearchWithIcon = Template.bind({});
78
+ SearchWithIcon.args = {
79
+ placeholder: "Search users...",
80
+ icon: IconSearch,
81
+ iconPosition: "left",
82
+ debounceMs: 300,
83
+ };
84
+
85
+ export const EmailWithDebounce = Template.bind({});
86
+ EmailWithDebounce.args = {
87
+ type: "email",
88
+ placeholder: "Enter email...",
89
+ icon: IconMail,
90
+ iconPosition: "left",
91
+ debounceMs: 500,
92
+ };
93
+
94
+ export const UserSearchWithIcon = Template.bind({});
95
+ UserSearchWithIcon.args = {
96
+ placeholder: "Search for users...",
97
+ icon: IconUser,
98
+ iconPosition: "left",
99
+ debounceMs: 400,
100
+ };
101
+
102
+ // Interactive example showing real-time vs debounced updates
103
+ const InteractiveTemplate: StoryFn<DebouncedInputProps> = (args: DebouncedInputProps) => {
104
+ const [realTimeValue, setRealTimeValue] = useState("");
105
+ const [debouncedValue, setDebouncedValue] = useState("");
106
+ const [updateCount, setUpdateCount] = useState(0);
107
+ const [debouncedUpdateCount, setDebouncedUpdateCount] = useState(0);
108
+
109
+ return (
110
+ <div className="al-p-4 al-max-w-lg al-space-y-6">
111
+ <div className="al-space-y-4">
112
+ <div>
113
+ <label className="al-block al-text-sm al-font-medium al-mb-2">
114
+ Real-time Input (no debounce)
115
+ </label>
116
+ <DebouncedInput
117
+ placeholder="Type here for real-time updates..."
118
+ debounceMs={0}
119
+ onChange={value => {
120
+ setRealTimeValue(value);
121
+ setUpdateCount(prev => prev + 1);
122
+ }}
123
+ />
124
+ </div>
125
+
126
+ <div>
127
+ <label className="al-block al-text-sm al-font-medium al-mb-2">
128
+ Debounced Input ({args.debounceMs}ms delay)
129
+ </label>
130
+ <DebouncedInput
131
+ {...args}
132
+ onChange={value => {
133
+ setDebouncedValue(value);
134
+ setDebouncedUpdateCount(prev => prev + 1);
135
+ }}
136
+ />
137
+ </div>
138
+ </div>
139
+
140
+ <div className="al-grid al-grid-cols-2 al-gap-4 al-text-sm">
141
+ <div className="al-space-y-2">
142
+ <h4 className="al-font-semibold">Real-time Updates</h4>
143
+ <div>
144
+ Value:{" "}
145
+ <code className="al-bg-gray-100 al-px-1 al-rounded">{realTimeValue || "empty"}</code>
146
+ </div>
147
+ <div>
148
+ Updates: <code className="al-bg-blue-100 al-px-1 al-rounded">{updateCount}</code>
149
+ </div>
150
+ </div>
151
+
152
+ <div className="al-space-y-2">
153
+ <h4 className="al-font-semibold">Debounced Updates</h4>
154
+ <div>
155
+ Value:{" "}
156
+ <code className="al-bg-gray-100 al-px-1 al-rounded">{debouncedValue || "empty"}</code>
157
+ </div>
158
+ <div>
159
+ Updates:{" "}
160
+ <code className="al-bg-green-100 al-px-1 al-rounded">{debouncedUpdateCount}</code>
161
+ </div>
162
+ </div>
163
+ </div>
164
+
165
+ <div className="al-text-xs al-text-gray-600">
166
+ Type quickly to see the difference between real-time and debounced updates. The debounced
167
+ input will only trigger onChange after you stop typing for {args.debounceMs}ms.
168
+ </div>
169
+ </div>
170
+ );
171
+ };
172
+
173
+ export const InteractiveComparison = InteractiveTemplate.bind({});
174
+ InteractiveComparison.args = {
175
+ placeholder: "Type here for debounced updates...",
176
+ debounceMs: 500,
177
+ icon: IconSearch,
178
+ iconPosition: "left",
179
+ };
@@ -1,8 +1,20 @@
1
1
  import { Meta, StoryFn } from "@storybook/react";
2
2
  import { Input } from "../shadcn";
3
3
  import { InputHTMLAttributes } from "react";
4
+ import {
5
+ IconUser,
6
+ IconMail,
7
+ IconSearch,
8
+ IconLock,
9
+ IconPhone,
10
+ IconMapPin,
11
+ IconCreditCard,
12
+ } from "@tabler/icons-react";
4
13
 
5
- type InputProps = InputHTMLAttributes<HTMLInputElement>;
14
+ type InputProps = InputHTMLAttributes<HTMLInputElement> & {
15
+ icon?: React.ComponentType<{ size?: string | number; className?: string }>;
16
+ iconPosition?: "left" | "right";
17
+ };
6
18
 
7
19
  export default {
8
20
  title: "Shadcn/Components/Input",
@@ -15,10 +27,18 @@ export default {
15
27
  control: "select",
16
28
  options: ["text", "password", "email", "number"],
17
29
  },
30
+ iconPosition: {
31
+ control: "select",
32
+ options: ["left", "right"],
33
+ },
18
34
  },
19
35
  } as Meta<typeof Input>;
20
36
 
21
- const Template: StoryFn<InputProps> = (args: InputProps) => <Input {...args} />;
37
+ const Template: StoryFn<InputProps> = (args: InputProps) => (
38
+ <div className="al-p-4 al-max-w-md">
39
+ <Input {...args} />
40
+ </div>
41
+ );
22
42
 
23
43
  export const Default = Template.bind({});
24
44
  Default.args = {
@@ -51,3 +71,70 @@ WithError.args = {
51
71
  className: "border-red-500",
52
72
  "aria-invalid": true,
53
73
  };
74
+
75
+ export const WithIconLeft = Template.bind({});
76
+ WithIconLeft.args = {
77
+ placeholder: "Search...",
78
+ icon: IconSearch,
79
+ iconPosition: "left",
80
+ };
81
+
82
+ export const WithIconRight = Template.bind({});
83
+ WithIconRight.args = {
84
+ placeholder: "Search...",
85
+ icon: IconSearch,
86
+ iconPosition: "right",
87
+ };
88
+
89
+ export const EmailWithIcon = Template.bind({});
90
+ EmailWithIcon.args = {
91
+ type: "email",
92
+ placeholder: "Enter your email",
93
+ icon: IconMail,
94
+ iconPosition: "left",
95
+ };
96
+
97
+ export const PasswordWithIcon = Template.bind({});
98
+ PasswordWithIcon.args = {
99
+ type: "password",
100
+ placeholder: "Enter password",
101
+ icon: IconLock,
102
+ iconPosition: "left",
103
+ };
104
+
105
+ export const UserInput = Template.bind({});
106
+ UserInput.args = {
107
+ placeholder: "Enter username",
108
+ icon: IconUser,
109
+ iconPosition: "left",
110
+ };
111
+
112
+ export const PhoneInput = Template.bind({});
113
+ PhoneInput.args = {
114
+ type: "tel",
115
+ placeholder: "Enter phone number",
116
+ icon: IconPhone,
117
+ iconPosition: "left",
118
+ };
119
+
120
+ export const AddressInput = Template.bind({});
121
+ AddressInput.args = {
122
+ placeholder: "Enter address",
123
+ icon: IconMapPin,
124
+ iconPosition: "left",
125
+ };
126
+
127
+ export const CreditCardInput = Template.bind({});
128
+ CreditCardInput.args = {
129
+ placeholder: "1234 5678 9012 3456",
130
+ icon: IconCreditCard,
131
+ iconPosition: "left",
132
+ };
133
+
134
+ export const DisabledWithIcon = Template.bind({});
135
+ DisabledWithIcon.args = {
136
+ placeholder: "Disabled with icon",
137
+ icon: IconUser,
138
+ iconPosition: "left",
139
+ disabled: true,
140
+ };
@@ -0,0 +1,147 @@
1
+ import { Meta, StoryFn } from "@storybook/react";
2
+ import { Tabs, TabsList, TabsTrigger, TabsContent } from "./Tabs";
3
+
4
+ export default {
5
+ title: "Shadcn/Components/Tabs",
6
+ component: Tabs,
7
+ argTypes: {
8
+ variant: {
9
+ control: { type: "select" },
10
+ options: ["default", "underlined"],
11
+ },
12
+ },
13
+ } as Meta;
14
+
15
+ export const Default: StoryFn = (args) => (
16
+ <Tabs defaultValue="tab1" {...args}>
17
+ <TabsList>
18
+ <TabsTrigger value="tab1">Tab 1</TabsTrigger>
19
+ <TabsTrigger value="tab2">Tab 2</TabsTrigger>
20
+ <TabsTrigger value="tab3">Tab 3</TabsTrigger>
21
+ </TabsList>
22
+ <TabsContent value="tab1">Content for Tab 1</TabsContent>
23
+ <TabsContent value="tab2">Content for Tab 2</TabsContent>
24
+ <TabsContent value="tab3">Content for Tab 3</TabsContent>
25
+ </Tabs>
26
+ );
27
+ Default.args = {
28
+ variant: "default",
29
+ };
30
+
31
+ export const Underlined: StoryFn = (args) => (
32
+ <Tabs defaultValue="overview" variant="underlined" {...args}>
33
+ <TabsList>
34
+ <TabsTrigger value="overview">Overview</TabsTrigger>
35
+ <TabsTrigger value="analytics">Analytics</TabsTrigger>
36
+ <TabsTrigger value="reports">Reports</TabsTrigger>
37
+ </TabsList>
38
+ <TabsContent value="overview">
39
+ <div className="al-p-4">
40
+ <h3 className="al-text-lg al-font-semibold al-mb-2">Overview</h3>
41
+ <p className="al-text-gray-600">Overview content goes here with detailed information.</p>
42
+ </div>
43
+ </TabsContent>
44
+ <TabsContent value="analytics">
45
+ <div className="al-p-4">
46
+ <h3 className="al-text-lg al-font-semibold al-mb-2">Analytics</h3>
47
+ <p className="al-text-gray-600">Analytics content with charts and data.</p>
48
+ </div>
49
+ </TabsContent>
50
+ <TabsContent value="reports">
51
+ <div className="al-p-4">
52
+ <h3 className="al-text-lg al-font-semibold al-mb-2">Reports</h3>
53
+ <p className="al-text-gray-600">Reports content with downloadable files.</p>
54
+ </div>
55
+ </TabsContent>
56
+ </Tabs>
57
+ );
58
+
59
+ export const WithRichContent: StoryFn = (args) => (
60
+ <Tabs defaultValue="profile" variant="underlined" {...args}>
61
+ <TabsList>
62
+ <TabsTrigger value="profile">Profile</TabsTrigger>
63
+ <TabsTrigger value="settings">Settings</TabsTrigger>
64
+ <TabsTrigger value="security">Security</TabsTrigger>
65
+ </TabsList>
66
+ <TabsContent value="profile">
67
+ <div className="al-p-4">
68
+ <h3 className="al-text-lg al-font-semibold al-mb-2">User Profile</h3>
69
+ <p className="al-text-gray-600 al-mb-4">Manage your profile information</p>
70
+ <div className="al-space-y-2">
71
+ <div className="al-flex al-items-center al-gap-2">
72
+ <span className="al-font-medium">Name:</span>
73
+ <span>John Doe</span>
74
+ </div>
75
+ <div className="al-flex al-items-center al-gap-2">
76
+ <span className="al-font-medium">Email:</span>
77
+ <span>john.doe@example.com</span>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </TabsContent>
82
+ <TabsContent value="settings">
83
+ <div className="al-p-4">
84
+ <h3 className="al-text-lg al-font-semibold al-mb-2">Settings</h3>
85
+ <div className="al-space-y-4">
86
+ <div className="al-flex al-items-center al-justify-between">
87
+ <span>Notifications</span>
88
+ <span className="al-text-sm al-text-gray-500">Enabled</span>
89
+ </div>
90
+ <div className="al-flex al-items-center al-justify-between">
91
+ <span>Dark Mode</span>
92
+ <span className="al-text-sm al-text-gray-500">Disabled</span>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </TabsContent>
97
+ <TabsContent value="security">
98
+ <div className="al-p-4">
99
+ <h3 className="al-text-lg al-font-semibold al-mb-2">Security</h3>
100
+ <p className="al-text-gray-600">Manage your security settings</p>
101
+ </div>
102
+ </TabsContent>
103
+ </Tabs>
104
+ );
105
+
106
+ export const ManyTabs: StoryFn = (args) => (
107
+ <Tabs defaultValue="home" variant="underlined" {...args}>
108
+ <TabsList>
109
+ <TabsTrigger value="home">Home</TabsTrigger>
110
+ <TabsTrigger value="about">About</TabsTrigger>
111
+ <TabsTrigger value="services">Services</TabsTrigger>
112
+ <TabsTrigger value="portfolio">Portfolio</TabsTrigger>
113
+ <TabsTrigger value="contact">Contact</TabsTrigger>
114
+ </TabsList>
115
+ <TabsContent value="home">Home content</TabsContent>
116
+ <TabsContent value="about">About content</TabsContent>
117
+ <TabsContent value="services">Services content</TabsContent>
118
+ <TabsContent value="portfolio">Portfolio content</TabsContent>
119
+ <TabsContent value="contact">Contact content</TabsContent>
120
+ </Tabs>
121
+ );
122
+
123
+ export const LongLabels: StoryFn = (args) => (
124
+ <Tabs defaultValue="dashboard" variant="underlined" {...args}>
125
+ <TabsList>
126
+ <TabsTrigger value="dashboard">Dashboard Overview</TabsTrigger>
127
+ <TabsTrigger value="analytics">Analytics & Reports</TabsTrigger>
128
+ <TabsTrigger value="users">User Management</TabsTrigger>
129
+ </TabsList>
130
+ <TabsContent value="dashboard">Dashboard overview content</TabsContent>
131
+ <TabsContent value="analytics">Analytics and reports content</TabsContent>
132
+ <TabsContent value="users">User management content</TabsContent>
133
+ </Tabs>
134
+ );
135
+
136
+ export const MinimalContent: StoryFn = (args) => (
137
+ <Tabs defaultValue="a" variant="underlined" {...args}>
138
+ <TabsList>
139
+ <TabsTrigger value="a">Tab A</TabsTrigger>
140
+ <TabsTrigger value="b">Tab B</TabsTrigger>
141
+ <TabsTrigger value="c">Tab C</TabsTrigger>
142
+ </TabsList>
143
+ <TabsContent value="a">A</TabsContent>
144
+ <TabsContent value="b">B</TabsContent>
145
+ <TabsContent value="c">C</TabsContent>
146
+ </Tabs>
147
+ );
@@ -1,4 +1,4 @@
1
- import { k as kt, p as vt, l as wt, m as rt, n as I, s as St, o as Et, q as Tt, r as et } from "./CoachForm.js";
1
+ import { q as kt, r as vt, v as wt, w as rt, x as I, y as St, z as Et, B as Tt, D as et } from "./CoachForm.js";
2
2
  import { s as q } from "./redux-toolkit.modern.js";
3
3
  import { i as It } from "./is_dark.js";
4
4
  var X = function() {
@@ -76,7 +76,7 @@ var X = function() {
76
76
  }
77
77
  },
78
78
  parse: function(r) {
79
- var a = this, h = [0], u = [], y = [null], c = [], M = this.table, x = "", N = 0, S = 0, L = 2, V = 1, H = c.slice.call(arguments, 1), m = Object.create(this.lexer), C = { yy: {} };
79
+ var a = this, h = [0], u = [], y = [null], c = [], M = this.table, x = "", N = 0, S = 0, L = 2, z = 1, H = c.slice.call(arguments, 1), m = Object.create(this.lexer), C = { yy: {} };
80
80
  for (var O in this.yy)
81
81
  Object.prototype.hasOwnProperty.call(this.yy, O) && (C.yy[O] = this.yy[O]);
82
82
  m.setInput(r, C.yy), C.yy.lexer = m, C.yy.parser = this, typeof m.yylloc > "u" && (m.yylloc = {});
@@ -86,17 +86,17 @@ var X = function() {
86
86
  typeof C.yy.parseError == "function" ? this.parseError = C.yy.parseError : this.parseError = Object.getPrototypeOf(this).parseError;
87
87
  function bt() {
88
88
  var P;
89
- return P = u.pop() || m.lex() || V, typeof P != "number" && (P instanceof Array && (u = P, P = u.pop()), P = a.symbols_[P] || P), P;
89
+ return P = u.pop() || m.lex() || z, typeof P != "number" && (P instanceof Array && (u = P, P = u.pop()), P = a.symbols_[P] || P), P;
90
90
  }
91
- for (var T, z, $, K, W = {}, j, A, tt, G; ; ) {
92
- if (z = h[h.length - 1], this.defaultActions[z] ? $ = this.defaultActions[z] : ((T === null || typeof T > "u") && (T = bt()), $ = M[z] && M[z][T]), typeof $ > "u" || !$.length || !$[0]) {
91
+ for (var T, V, $, K, W = {}, j, A, tt, G; ; ) {
92
+ if (V = h[h.length - 1], this.defaultActions[V] ? $ = this.defaultActions[V] : ((T === null || typeof T > "u") && (T = bt()), $ = M[V] && M[V][T]), typeof $ > "u" || !$.length || !$[0]) {
93
93
  var Q = "";
94
94
  G = [];
95
- for (j in M[z])
95
+ for (j in M[V])
96
96
  this.terminals_[j] && j > L && G.push("'" + this.terminals_[j] + "'");
97
97
  m.showPosition ? Q = "Parse error on line " + (N + 1) + `:
98
98
  ` + m.showPosition() + `
99
- Expecting ` + G.join(", ") + ", got '" + (this.terminals_[T] || T) + "'" : Q = "Parse error on line " + (N + 1) + ": Unexpected " + (T == V ? "end of input" : "'" + (this.terminals_[T] || T) + "'"), this.parseError(Q, {
99
+ Expecting ` + G.join(", ") + ", got '" + (this.terminals_[T] || T) + "'" : Q = "Parse error on line " + (N + 1) + ": Unexpected " + (T == z ? "end of input" : "'" + (this.terminals_[T] || T) + "'"), this.parseError(Q, {
100
100
  text: m.match,
101
101
  token: this.terminals_[T] || T,
102
102
  line: m.yylineno,
@@ -105,7 +105,7 @@ Expecting ` + G.join(", ") + ", got '" + (this.terminals_[T] || T) + "'" : Q = "
105
105
  });
106
106
  }
107
107
  if ($[0] instanceof Array && $.length > 1)
108
- throw new Error("Parse Error: multiple actions possible at state: " + z + ", token: " + T);
108
+ throw new Error("Parse Error: multiple actions possible at state: " + V + ", token: " + T);
109
109
  switch ($[0]) {
110
110
  case 1:
111
111
  h.push(T), y.push(m.yytext), c.push(m.yylloc), h.push($[1]), T = null, S = m.yyleng, x = m.yytext, N = m.yylineno, J = m.yylloc;
@@ -489,7 +489,7 @@ const Y = [], U = [], B = [], ct = () => kt, ot = (n, t, e) => {
489
489
  );
490
490
  };
491
491
  let it = -1;
492
- const Vt = function(n, t, e) {
492
+ const zt = function(n, t, e) {
493
493
  const s = t.x + e.width / 2, i = n.append("g");
494
494
  it++;
495
495
  const o = 300 + 5 * 30;
@@ -510,7 +510,7 @@ const Vt = function(n, t, e) {
510
510
  e,
511
511
  t.colour
512
512
  );
513
- }, zt = function(n, t) {
513
+ }, Vt = function(n, t) {
514
514
  Z(n, {
515
515
  x: t.startx,
516
516
  y: t.starty,
@@ -596,8 +596,8 @@ const Ft = function(n, t, e, s) {
596
596
  drawSection: Ct,
597
597
  drawText: ft,
598
598
  drawLabel: Ht,
599
- drawTask: Vt,
600
- drawBackgroundRect: zt,
599
+ drawTask: zt,
600
+ drawBackgroundRect: Vt,
601
601
  getTextObj: Rt,
602
602
  getNoteRect: D,
603
603
  initGraphics: Wt,
@@ -644,8 +644,8 @@ const Ft = function(n, t, e, s) {
644
644
  width: 150,
645
645
  padding: 20,
646
646
  maxHeight: w
647
- }, V = R.getVirtualNodeHeight(d, L, i);
648
- I.debug("taskHeight before draw", V), w = Math.max(w, V + 20), y = Math.max(y, S.events.length);
647
+ }, z = R.getVirtualNodeHeight(d, L, i);
648
+ I.debug("taskHeight before draw", z), w = Math.max(w, z + 20), y = Math.max(y, S.events.length);
649
649
  let H = 0;
650
650
  for (let m = 0; m < S.events.length; m++) {
651
651
  const O = {
@@ -670,8 +670,8 @@ const Ft = function(n, t, e, s) {
670
670
  maxHeight: b
671
671
  };
672
672
  I.debug("sectionNode", S);
673
- const L = d.append("g"), V = R.drawNode(L, S, h, i);
674
- I.debug("sectionNode output", V), L.attr("transform", `translate(${r}, ${k})`), a += b + 50;
673
+ const L = d.append("g"), z = R.drawNode(L, S, h, i);
674
+ I.debug("sectionNode output", z), L.attr("transform", `translate(${r}, ${k})`), a += b + 50;
675
675
  const H = f.filter((m) => m.section === N);
676
676
  H.length > 0 && st(
677
677
  d,