@astryxdesign/lab 0.1.7-canary.fb9c68c → 0.1.8-canary.0db5dfd

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 (51) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/CircularProgress/CircularProgress.d.ts +40 -11
  3. package/dist/CircularProgress/CircularProgress.d.ts.map +1 -1
  4. package/dist/CircularProgress/CircularProgress.js +66 -25
  5. package/dist/RichTextEditor/RichTextEditor.d.ts +145 -0
  6. package/dist/RichTextEditor/RichTextEditor.d.ts.map +1 -0
  7. package/dist/RichTextEditor/RichTextEditor.js +262 -0
  8. package/dist/RichTextEditor/RichTextView.d.ts +65 -0
  9. package/dist/RichTextEditor/RichTextView.d.ts.map +1 -0
  10. package/dist/RichTextEditor/RichTextView.js +122 -0
  11. package/dist/RichTextEditor/editorTheme.d.ts +7 -0
  12. package/dist/RichTextEditor/editorTheme.d.ts.map +1 -0
  13. package/dist/RichTextEditor/editorTheme.js +75 -0
  14. package/dist/RichTextEditor/index.d.ts +15 -0
  15. package/dist/RichTextEditor/index.d.ts.map +1 -0
  16. package/dist/RichTextEditor/index.js +16 -0
  17. package/dist/Schedule/shared.d.ts.map +1 -1
  18. package/dist/Stepper/Step.d.ts +12 -6
  19. package/dist/Stepper/Step.d.ts.map +1 -1
  20. package/dist/Stepper/Step.js +335 -59
  21. package/dist/Stepper/StepStatus.d.ts +10 -10
  22. package/dist/Stepper/Stepper.d.ts +14 -4
  23. package/dist/Stepper/Stepper.d.ts.map +1 -1
  24. package/dist/Stepper/Stepper.js +30 -10
  25. package/dist/Stepper/StepperContext.d.ts +16 -0
  26. package/dist/Stepper/StepperContext.d.ts.map +1 -1
  27. package/dist/Stepper/StepperContext.js +10 -0
  28. package/dist/Stepper/index.d.ts +1 -1
  29. package/dist/Stepper/index.d.ts.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +5 -1
  33. package/dist/lab.css +29 -1
  34. package/package.json +49 -6
  35. package/src/CircularProgress/CircularProgress.doc.mjs +88 -18
  36. package/src/CircularProgress/CircularProgress.test.tsx +210 -31
  37. package/src/CircularProgress/CircularProgress.tsx +108 -25
  38. package/src/RichTextEditor/RichTextEditor.doc.mjs +147 -0
  39. package/src/RichTextEditor/RichTextEditor.test.tsx +220 -0
  40. package/src/RichTextEditor/RichTextEditor.tsx +466 -0
  41. package/src/RichTextEditor/RichTextView.tsx +184 -0
  42. package/src/RichTextEditor/editorTheme.ts +120 -0
  43. package/src/RichTextEditor/index.ts +26 -0
  44. package/src/Schedule/shared.tsx +1 -3
  45. package/src/Stepper/Step.tsx +494 -51
  46. package/src/Stepper/StepStatus.ts +10 -10
  47. package/src/Stepper/Stepper.test.tsx +134 -0
  48. package/src/Stepper/Stepper.tsx +52 -14
  49. package/src/Stepper/StepperContext.ts +18 -3
  50. package/src/Stepper/index.ts +4 -1
  51. package/src/index.ts +13 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @xds/lab
2
2
 
3
+ # 0.1.8
4
+
5
+ ---
6
+
3
7
  # 0.1.7
4
8
 
5
9
  ---
@@ -5,11 +5,10 @@
5
5
  * @position Core implementation; consumed by index.ts
6
6
  *
7
7
  * SYNC: When modified, update these files to stay in sync:
8
- * - /packages/core/src/CircularProgress/CircularProgress.doc.mjs (props table, features, implementation notes)
9
- * - /packages/core/src/CircularProgress/CircularProgress.test.tsx (tests for new/changed behavior)
10
- * - /packages/core/src/CircularProgress/index.ts (exports if types change)
8
+ * - /packages/lab/src/CircularProgress/CircularProgress.doc.mjs (props table, features, implementation notes)
9
+ * - /packages/lab/src/CircularProgress/CircularProgress.test.tsx (tests for new/changed behavior)
10
+ * - /packages/lab/src/CircularProgress/index.ts (exports if types change)
11
11
  * - /apps/storybook/stories/CircularProgress.stories.tsx (storybook stories)
12
- * - /packages/cli/templates/blocks/components/CircularProgress/ (showcase blocks)
13
12
  */
14
13
  import { type ReactNode } from 'react';
15
14
  import type { BaseProps } from '@astryxdesign/core';
@@ -19,7 +18,7 @@ import type { BaseProps } from '@astryxdesign/core';
19
18
  * Theme packages can add custom variants via TypeScript module augmentation:
20
19
  * @example
21
20
  * ```
22
- * declare module '@astryxdesign/core/CircularProgress' {
21
+ * declare module '@astryxdesign/lab' {
23
22
  * interface CircularProgressVariantMap {
24
23
  * 'brand': true;
25
24
  * }
@@ -40,7 +39,7 @@ export interface CircularProgressProps extends BaseProps<HTMLDivElement> {
40
39
  ref?: React.Ref<HTMLDivElement>;
41
40
  /**
42
41
  * Current value of the circular progress.
43
- * When omitted, the component renders an indeterminate spinning animation.
42
+ * Ignored when `isIndeterminate` is true.
44
43
  */
45
44
  value?: number;
46
45
  /**
@@ -57,9 +56,22 @@ export interface CircularProgressProps extends BaseProps<HTMLDivElement> {
57
56
  * @default true
58
57
  */
59
58
  isLabelHidden?: boolean;
59
+ /**
60
+ * When true, displays the formatted value (e.g. "75%") in the center of
61
+ * the ring. Ignored when `isIndeterminate` is true or when `children`
62
+ * provide custom center content.
63
+ * @default false
64
+ */
65
+ hasValueLabel?: boolean;
66
+ /**
67
+ * Custom formatter for the value label.
68
+ * @default (value, max) => `${Math.round((value / max) * 100)}%`
69
+ */
70
+ formatValueLabel?: (value: number, max: number) => string;
60
71
  /**
61
72
  * Content displayed in the center of the ring.
62
73
  * Typically a percentage string, icon, or custom content.
74
+ * Takes precedence over `hasValueLabel`.
63
75
  */
64
76
  children?: ReactNode;
65
77
  /**
@@ -75,6 +87,20 @@ export interface CircularProgressProps extends BaseProps<HTMLDivElement> {
75
87
  * @default 'accent'
76
88
  */
77
89
  variant?: CircularProgressVariant;
90
+ /**
91
+ * When true, renders an animated indeterminate progress indicator.
92
+ * Use when the progress amount is unknown (e.g. loading, processing).
93
+ * The `value` and `hasValueLabel` props are ignored in this mode.
94
+ * Respects `prefers-reduced-motion` by slowing the animation.
95
+ * @default false
96
+ */
97
+ isIndeterminate?: boolean;
98
+ /**
99
+ * When true, the circular progress is visually disabled — the ring and
100
+ * text use disabled colors. Use for canceled or inactive operations.
101
+ * @default false
102
+ */
103
+ isDisabled?: boolean;
78
104
  /**
79
105
  * Test ID for testing utilities.
80
106
  */
@@ -85,16 +111,19 @@ export interface CircularProgressProps extends BaseProps<HTMLDivElement> {
85
111
  *
86
112
  * In determinate mode, displays a known value as an arc fill.
87
113
  * In indeterminate mode, shows an animated spinning indicator.
88
- * Supports center content via children for labels, percentages, or icons.
114
+ * Supports center content via children for labels, percentages, or icons,
115
+ * or an automatic formatted value label via `hasValueLabel`.
89
116
  *
90
117
  * @example
91
118
  * ```
92
- * <CircularProgress value={75} label="Upload progress" />
93
- * <CircularProgress value={75} label="Progress" max={100}>75%</CircularProgress>
94
- * <CircularProgress label="Loading..." />
119
+ * <CircularProgress value={75} label="Upload progress" hasValueLabel />
120
+ * <CircularProgress isIndeterminate label="Loading..." />
121
+ * <CircularProgress value={3.2} max={5} label="Disk usage" hasValueLabel
122
+ * formatValueLabel={(v, m) => `${v} GB / ${m} GB`} />
123
+ * <CircularProgress value={30} label="Canceled" isDisabled hasValueLabel />
95
124
  * ```
96
125
  */
97
- export declare function CircularProgress({ value, max, label, isLabelHidden, children, size, variant, xstyle, className, style, 'data-testid': dataTestId, ref, ...rest }: CircularProgressProps): import("react").JSX.Element;
126
+ export declare function CircularProgress({ value, max, label, isLabelHidden, hasValueLabel, formatValueLabel, children, size, variant, isIndeterminate, isDisabled, xstyle, className, style, 'data-testid': dataTestId, ref, ...rest }: CircularProgressProps): import("react").JSX.Element;
98
127
  export declare namespace CircularProgress {
99
128
  var displayName: string;
100
129
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CircularProgress.d.ts","sourceRoot":"","sources":["../../src/CircularProgress/CircularProgress.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAY5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAGlD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC;CACf;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,0BAA0B,CAAC;AAEvE,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAQtD,MAAM,WAAW,qBAAsB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACtE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAiJD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,GAAS,EACT,KAAK,EACL,aAAoB,EACpB,QAAQ,EACR,IAAW,EACX,OAAkB,EAClB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,UAAU,EACzB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,qBAAqB,+BAyFvB;yBAvGe,gBAAgB"}
1
+ {"version":3,"file":"CircularProgress.d.ts","sourceRoot":"","sources":["../../src/CircularProgress/CircularProgress.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAY5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAGlD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC;CACf;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,0BAA0B,CAAC;AAEvE,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAQtD,MAAM,WAAW,qBAAsB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACtE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1D;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAqKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAS,EACT,GAAS,EACT,KAAK,EACL,aAAoB,EACpB,aAAqB,EACrB,gBAA0C,EAC1C,QAAQ,EACR,IAAW,EACX,OAAkB,EAClB,eAAuB,EACvB,UAAkB,EAClB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,UAAU,EACzB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,qBAAqB,+BAuHvB;yBAzIe,gBAAgB"}
@@ -9,11 +9,10 @@
9
9
  * @position Core implementation; consumed by index.ts
10
10
  *
11
11
  * SYNC: When modified, update these files to stay in sync:
12
- * - /packages/core/src/CircularProgress/CircularProgress.doc.mjs (props table, features, implementation notes)
13
- * - /packages/core/src/CircularProgress/CircularProgress.test.tsx (tests for new/changed behavior)
14
- * - /packages/core/src/CircularProgress/index.ts (exports if types change)
12
+ * - /packages/lab/src/CircularProgress/CircularProgress.doc.mjs (props table, features, implementation notes)
13
+ * - /packages/lab/src/CircularProgress/CircularProgress.test.tsx (tests for new/changed behavior)
14
+ * - /packages/lab/src/CircularProgress/index.ts (exports if types change)
15
15
  * - /apps/storybook/stories/CircularProgress.stories.tsx (storybook stories)
16
- * - /packages/cli/templates/blocks/components/CircularProgress/ (showcase blocks)
17
16
  */
18
17
  import { useId } from 'react';
19
18
  import * as stylex from '@stylexjs/stylex';
@@ -28,7 +27,7 @@ import { themeProps } from '@astryxdesign/core/utils';
28
27
  * Theme packages can add custom variants via TypeScript module augmentation:
29
28
  * @example
30
29
  * ```
31
- * declare module '@astryxdesign/core/CircularProgress' {
30
+ * declare module '@astryxdesign/lab' {
32
31
  * interface CircularProgressVariantMap {
33
32
  * 'brand': true;
34
33
  * }
@@ -118,6 +117,10 @@ const variantStyles = {
118
117
  neutral: {
119
118
  kjVXCG: "xuxf9kk",
120
119
  $$css: true
120
+ },
121
+ disabled: {
122
+ kjVXCG: "xuxf9kk",
123
+ $$css: true
121
124
  }
122
125
  };
123
126
  const trackVariantStyles = {
@@ -142,29 +145,40 @@ const trackVariantStyles = {
142
145
  $$css: true
143
146
  }
144
147
  };
148
+ function defaultFormatValueLabel(value, max) {
149
+ const pct = max > 0 ? Math.round(value / max * 100) : 0;
150
+ return `${pct}%`;
151
+ }
145
152
 
146
153
  /**
147
154
  * A circular/radial progress indicator that shows completion as a ring.
148
155
  *
149
156
  * In determinate mode, displays a known value as an arc fill.
150
157
  * In indeterminate mode, shows an animated spinning indicator.
151
- * Supports center content via children for labels, percentages, or icons.
158
+ * Supports center content via children for labels, percentages, or icons,
159
+ * or an automatic formatted value label via `hasValueLabel`.
152
160
  *
153
161
  * @example
154
162
  * ```
155
- * <CircularProgress value={75} label="Upload progress" />
156
- * <CircularProgress value={75} label="Progress" max={100}>75%</CircularProgress>
157
- * <CircularProgress label="Loading..." />
163
+ * <CircularProgress value={75} label="Upload progress" hasValueLabel />
164
+ * <CircularProgress isIndeterminate label="Loading..." />
165
+ * <CircularProgress value={3.2} max={5} label="Disk usage" hasValueLabel
166
+ * formatValueLabel={(v, m) => `${v} GB / ${m} GB`} />
167
+ * <CircularProgress value={30} label="Canceled" isDisabled hasValueLabel />
158
168
  * ```
159
169
  */
160
170
  export function CircularProgress({
161
- value,
171
+ value = 0,
162
172
  max = 100,
163
173
  label,
164
174
  isLabelHidden = true,
175
+ hasValueLabel = false,
176
+ formatValueLabel = defaultFormatValueLabel,
165
177
  children,
166
178
  size = 'md',
167
179
  variant = 'accent',
180
+ isIndeterminate = false,
181
+ isDisabled = false,
168
182
  xstyle,
169
183
  className,
170
184
  style,
@@ -173,19 +187,29 @@ export function CircularProgress({
173
187
  ...rest
174
188
  }) {
175
189
  const labelId = useId();
176
- const isIndeterminate = value == null;
177
190
  const {
178
191
  diameter,
179
192
  strokeWidth
180
193
  } = SIZE_CONFIG[size];
181
194
  const radius = (diameter - strokeWidth) / 2;
182
195
  const circumference = 2 * Math.PI * radius;
183
- const resolvedValue = value ?? 0;
184
- const clampedValue = Math.min(Math.max(0, resolvedValue), max);
185
- const percentage = max > 0 ? clampedValue / max : 0;
196
+
197
+ // A non-finite value or max (e.g. a NaN from an upstream `loaded / total`
198
+ // with total 0) would otherwise leak into aria-valuenow, the value label,
199
+ // and the arc geometry as the string "NaN". Treat it as empty progress,
200
+ // matching the max=0 handling below.
201
+ const safeValue = Number.isFinite(value) ? value : 0;
202
+ const safeMax = Number.isFinite(max) ? max : 0;
203
+ const clampedValue = Math.min(Math.max(0, safeValue), safeMax);
204
+ const percentage = safeMax > 0 ? clampedValue / safeMax : 0;
186
205
  const dashoffset = circumference * (1 - percentage);
206
+ const valueText = formatValueLabel(clampedValue, safeMax);
187
207
  const center = diameter / 2;
188
208
  const showLabel = !isLabelHidden;
209
+ const showValueLabel = hasValueLabel && !isIndeterminate;
210
+ const centerContent = children != null ? children : showValueLabel ? valueText : null;
211
+ const fillVariant = isDisabled ? 'disabled' : variant;
212
+ const trackVariant = isDisabled ? 'neutral' : variant;
189
213
  return /*#__PURE__*/_jsxs("div", {
190
214
  ref: ref,
191
215
  ...mergeProps(themeProps('circular-progress', {
@@ -200,21 +224,28 @@ export function CircularProgress({
200
224
  0: {
201
225
  className: "x10l6tqk x1i1rx1s xjm9jq1 x1717udv xkdpibf xb3r6kr xzpqnlu xuxw1ft xc342km"
202
226
  },
203
- 1: {
227
+ 2: {
204
228
  className: "x141an7d x1ltkj2j x1e4wzip xv1l7n4"
229
+ },
230
+ 1: {
231
+ className: "x10l6tqk x1i1rx1s xjm9jq1 x1717udv xkdpibf xb3r6kr xzpqnlu xuxw1ft xc342km xnbbluu"
232
+ },
233
+ 3: {
234
+ className: "x141an7d x1ltkj2j x1e4wzip xnbbluu"
205
235
  }
206
- }[!!showLabel << 0],
236
+ }[!!showLabel << 1 | !!(showLabel && isDisabled) << 0],
207
237
  children: label
208
238
  }), /*#__PURE__*/_jsxs("div", {
209
239
  ...{
210
240
  className: "x1n2onr6 x3nfvp2"
211
241
  },
212
242
  children: [/*#__PURE__*/_jsxs("svg", {
213
- role: isIndeterminate ? 'progressbar' : 'meter',
243
+ role: "progressbar",
214
244
  "aria-labelledby": labelId,
215
245
  "aria-valuenow": isIndeterminate ? undefined : clampedValue,
216
246
  "aria-valuemin": isIndeterminate ? undefined : 0,
217
- "aria-valuemax": isIndeterminate ? undefined : max,
247
+ "aria-valuemax": isIndeterminate ? undefined : safeMax,
248
+ "aria-valuetext": isIndeterminate ? undefined : valueText,
218
249
  width: diameter,
219
250
  height: diameter,
220
251
  viewBox: `0 0 ${diameter} ${diameter}`,
@@ -227,23 +258,23 @@ export function CircularProgress({
227
258
  }
228
259
  }[!!isIndeterminate << 0],
229
260
  children: [/*#__PURE__*/_jsx("circle", {
230
- ...mergeProps(themeProps('circular-progress-track'), stylex.props(styles.track, trackVariantStyles[variant])),
261
+ ...mergeProps(themeProps('circular-progress-track'), stylex.props(styles.track, trackVariantStyles[trackVariant])),
231
262
  cx: center,
232
263
  cy: center,
233
264
  r: radius,
234
265
  strokeWidth: strokeWidth
235
266
  }), isIndeterminate ? /*#__PURE__*/_jsx("circle", {
236
267
  ...mergeProps(themeProps('circular-progress-fill', {
237
- variant
238
- }), stylex.props(styles.fillIndeterminate, variantStyles[variant])),
268
+ variant: fillVariant
269
+ }), stylex.props(styles.fillIndeterminate, variantStyles[fillVariant])),
239
270
  cx: center,
240
271
  cy: center,
241
272
  r: radius,
242
273
  strokeWidth: strokeWidth
243
274
  }) : /*#__PURE__*/_jsx("circle", {
244
275
  ...mergeProps(themeProps('circular-progress-fill', {
245
- variant
246
- }), stylex.props(styles.fill, variantStyles[variant])),
276
+ variant: fillVariant
277
+ }), stylex.props(styles.fill, variantStyles[fillVariant])),
247
278
  cx: center,
248
279
  cy: center,
249
280
  r: radius,
@@ -251,11 +282,21 @@ export function CircularProgress({
251
282
  strokeDasharray: circumference,
252
283
  strokeDashoffset: dashoffset
253
284
  })]
254
- }), children != null && /*#__PURE__*/_jsx("div", {
285
+ }), centerContent != null && /*#__PURE__*/_jsx("div", {
255
286
  ...{
256
287
  className: "x10l6tqk x10a8y8t x78zum5 x6s0dn4 xl56j7k x47corl"
257
288
  },
258
- children: children
289
+ children: children != null ? children : /*#__PURE__*/_jsx("span", {
290
+ ...{
291
+ 0: {
292
+ className: "x141an7d x1ltkj2j x1sodnla xv1l7n4"
293
+ },
294
+ 1: {
295
+ className: "x141an7d x1ltkj2j x1sodnla xnbbluu"
296
+ }
297
+ }[!!isDisabled << 0],
298
+ children: valueText
299
+ })
259
300
  })]
260
301
  })]
261
302
  });
@@ -0,0 +1,145 @@
1
+ /**
2
+ * @file RichTextEditor.tsx
3
+ * @input Uses React, useId, Lexical (lexical + @lexical/react), Field, design tokens
4
+ * @output Exports RichTextEditor component, RichTextEditorProps, RichTextEditorStatus,
5
+ * RichTextEditorStatusType, RichTextEditorSize
6
+ * @position Experimental (lab) implementation; consumed by RichTextEditor/index.ts and
7
+ * re-exported from @astryxdesign/lab. Tested by RichTextEditor.test.tsx.
8
+ *
9
+ * SYNC: When modified, update these files to stay in sync:
10
+ * - /packages/lab/src/RichTextEditor/RichTextEditor.doc.mjs (props table, features, implementation notes)
11
+ * - /packages/lab/src/RichTextEditor/RichTextEditor.test.tsx (tests for new/changed behavior)
12
+ * - /packages/lab/src/RichTextEditor/index.ts (exports if types change)
13
+ * - /packages/lab/src/index.ts (barrel re-export)
14
+ * - /apps/storybook/stories/RichTextEditor.stories.tsx (storybook stories)
15
+ *
16
+ * NOTE: This is an EXPERIMENTAL component in @astryxdesign/lab (published only under
17
+ * the `@canary` dist-tag, never as stable `latest`). It is the initial landing for the
18
+ * OSS Lexical editor RFC; the goal is graduation to @astryxdesign/core after the
19
+ * Component Specification Protocol. `lexical` and `@lexical/*` are OPTIONAL peer
20
+ * dependencies — install them to use this component.
21
+ */
22
+ import { type ReactNode } from 'react';
23
+ import type { BaseProps } from '@astryxdesign/core';
24
+ import type { SizeValue } from '@astryxdesign/core/utils';
25
+ import type { EditorState, Klass, LexicalEditor, LexicalNode } from 'lexical';
26
+ export type RichTextEditorStatusType = 'warning' | 'error' | 'success';
27
+ export type RichTextEditorSize = 'sm' | 'md' | 'lg';
28
+ export interface RichTextEditorStatus {
29
+ /** The type of status to display. */
30
+ type: RichTextEditorStatusType;
31
+ /** Optional message to display below the editor. */
32
+ message?: string;
33
+ }
34
+ export interface RichTextEditorProps extends Omit<BaseProps, 'onChange' | 'defaultValue'> {
35
+ /** Label text for the editor (always rendered for accessibility). */
36
+ label: string;
37
+ /**
38
+ * Whether to visually hide the label (still accessible to screen readers).
39
+ * @default false
40
+ */
41
+ isLabelHidden?: boolean;
42
+ /** Description text displayed between the label and editor. */
43
+ description?: string;
44
+ /**
45
+ * Whether the field is optional. Mutually exclusive with isRequired.
46
+ * @default false
47
+ */
48
+ isOptional?: boolean;
49
+ /**
50
+ * Whether the field is required. Mutually exclusive with isOptional.
51
+ * @default false
52
+ */
53
+ isRequired?: boolean;
54
+ /**
55
+ * Initial serialized editor state (a JSON string produced by
56
+ * `JSON.stringify(editorState.toJSON())`), used to seed the editor on mount.
57
+ * The editor is uncontrolled: this is read once.
58
+ */
59
+ defaultValue?: string;
60
+ /**
61
+ * Callback fired when the editor content changes. Receives the current
62
+ * `EditorState` and the `LexicalEditor` instance. Serialize with
63
+ * `editorState.toJSON()` for persistence.
64
+ */
65
+ onChange?: (editorState: EditorState, editor: LexicalEditor) => void;
66
+ /** Placeholder text shown when the editor is empty. */
67
+ placeholder?: string;
68
+ /**
69
+ * Whether the editor is read-only (non-editable).
70
+ * @default false
71
+ */
72
+ isReadOnly?: boolean;
73
+ /**
74
+ * Whether the editor is disabled (non-editable, dimmed).
75
+ * @default false
76
+ */
77
+ isDisabled?: boolean;
78
+ /**
79
+ * Status indicator. When set, displays a colored border. If message is
80
+ * provided, displays a message box below the editor.
81
+ */
82
+ status?: RichTextEditorStatus;
83
+ /**
84
+ * Width of the field. Numbers are treated as pixels, strings are used as-is
85
+ * (e.g. `'100%'`).
86
+ */
87
+ width?: SizeValue;
88
+ /** Tooltip text to display in an info icon at the end of the label. */
89
+ labelTooltip?: string;
90
+ /**
91
+ * The size of the editor, affecting internal padding.
92
+ * @default 'md'
93
+ */
94
+ size?: RichTextEditorSize;
95
+ /**
96
+ * Additional Lexical nodes to register beyond the default OSS set
97
+ * (Heading, Quote, List, Link, Code). Use this extension point to plug in
98
+ * custom nodes (e.g. mentions, images) without forking the editor.
99
+ */
100
+ nodes?: ReadonlyArray<Klass<LexicalNode>>;
101
+ /**
102
+ * Additional Lexical plugins to render inside the composer. Use this to
103
+ * compose extra behaviour (toolbars, mentions, autolink, etc.) on top of the
104
+ * base editor. Plugins receive the editor via `useLexicalComposerContext()`.
105
+ */
106
+ plugins?: ReactNode;
107
+ /**
108
+ * Whether to enable Markdown shortcut typing (e.g. `# ` for a heading,
109
+ * `- ` for a list). Uses the default `@lexical/markdown` transformers.
110
+ * @default true
111
+ */
112
+ hasMarkdownShortcuts?: boolean;
113
+ /** Whether to automatically focus the editor on mount. @default false */
114
+ hasAutoFocus?: boolean;
115
+ /**
116
+ * The Lexical composer namespace, used for editor identity.
117
+ * @default 'astryx-editor'
118
+ */
119
+ namespace?: string;
120
+ }
121
+ /**
122
+ * A WYSIWYG rich-text editor built on Lexical, styled with Astryx design
123
+ * tokens. Experimental — ships from `@astryxdesign/lab` (canary). `lexical` and
124
+ * `@lexical/*` are optional peer dependencies — install them to use this
125
+ * component.
126
+ *
127
+ * The editor is intentionally minimal and extensible: pass `nodes` and
128
+ * `plugins` to layer richer behaviour (toolbars, mentions, hover cards) on top
129
+ * without forking.
130
+ *
131
+ * @example
132
+ * ```
133
+ * import {RichTextEditor} from '@astryxdesign/lab';
134
+ * <RichTextEditor
135
+ * label="Notes"
136
+ * placeholder="Write something..."
137
+ * onChange={state => save(JSON.stringify(state.toJSON()))}
138
+ * />
139
+ * ```
140
+ */
141
+ export declare function RichTextEditor({ label, isLabelHidden, description, isOptional, isRequired, defaultValue, onChange, placeholder, isReadOnly, isDisabled, status, width, labelTooltip, size: sizeProp, nodes, plugins, hasMarkdownShortcuts, hasAutoFocus, namespace, xstyle, className, style, ...rest }: RichTextEditorProps): import("react").JSX.Element;
142
+ export declare namespace RichTextEditor {
143
+ var displayName: string;
144
+ }
145
+ //# sourceMappingURL=RichTextEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextEditor.d.ts","sourceRoot":"","sources":["../../src/RichTextEditor/RichTextEditor.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAA2B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAgB/D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAuBxD,OAAO,KAAK,EACV,WAAW,EACX,KAAK,EACL,aAAa,EACb,WAAW,EAEZ,MAAM,SAAS,CAAC;AAiEjB,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvE,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,SAAS,EACT,UAAU,GAAG,cAAc,CAC5B;IACC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACrE,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC1C;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,MAAM,EACN,KAAK,EACL,YAAY,EACZ,IAAI,EAAE,QAAQ,EACd,KAAK,EACL,OAAO,EACP,oBAA2B,EAC3B,YAAoB,EACpB,SAA2B,EAC3B,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,mBAAmB,+BAkHrB;yBA1Ie,cAAc"}