@cdx-ui/components 0.0.1-beta.90 → 0.0.1-beta.92

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 (49) hide show
  1. package/lib/commonjs/components/CLAUDE.md +2 -1
  2. package/lib/commonjs/components/Input/styles.js +4 -3
  3. package/lib/commonjs/components/Input/styles.js.map +1 -1
  4. package/lib/commonjs/components/Select/styles.js +4 -2
  5. package/lib/commonjs/components/Select/styles.js.map +1 -1
  6. package/lib/commonjs/components/Textarea/index.js +135 -0
  7. package/lib/commonjs/components/Textarea/index.js.map +1 -0
  8. package/lib/commonjs/components/Textarea/styles.js +49 -0
  9. package/lib/commonjs/components/Textarea/styles.js.map +1 -0
  10. package/lib/commonjs/components/index.js +12 -0
  11. package/lib/commonjs/components/index.js.map +1 -1
  12. package/lib/commonjs/figma/Field.Textarea.figma.js +57 -0
  13. package/lib/commonjs/figma/Field.Textarea.figma.js.map +1 -0
  14. package/lib/commonjs/figma/Textarea.figma.js +47 -0
  15. package/lib/commonjs/figma/Textarea.figma.js.map +1 -0
  16. package/lib/module/components/CLAUDE.md +2 -1
  17. package/lib/module/components/Input/styles.js +4 -3
  18. package/lib/module/components/Input/styles.js.map +1 -1
  19. package/lib/module/components/Select/styles.js +4 -2
  20. package/lib/module/components/Select/styles.js.map +1 -1
  21. package/lib/module/components/Textarea/index.js +132 -0
  22. package/lib/module/components/Textarea/index.js.map +1 -0
  23. package/lib/module/components/Textarea/styles.js +45 -0
  24. package/lib/module/components/Textarea/styles.js.map +1 -0
  25. package/lib/module/components/index.js +1 -0
  26. package/lib/module/components/index.js.map +1 -1
  27. package/lib/module/figma/Field.Textarea.figma.js +51 -0
  28. package/lib/module/figma/Field.Textarea.figma.js.map +1 -0
  29. package/lib/module/figma/Textarea.figma.js +41 -0
  30. package/lib/module/figma/Textarea.figma.js.map +1 -0
  31. package/lib/typescript/components/Input/styles.d.ts.map +1 -1
  32. package/lib/typescript/components/Select/styles.d.ts.map +1 -1
  33. package/lib/typescript/components/Textarea/index.d.ts +26 -0
  34. package/lib/typescript/components/Textarea/index.d.ts.map +1 -0
  35. package/lib/typescript/components/Textarea/styles.d.ts +11 -0
  36. package/lib/typescript/components/Textarea/styles.d.ts.map +1 -0
  37. package/lib/typescript/components/index.d.ts +1 -0
  38. package/lib/typescript/components/index.d.ts.map +1 -1
  39. package/lib/typescript/figma/Field.Textarea.figma.d.ts +8 -0
  40. package/lib/typescript/figma/Field.Textarea.figma.d.ts.map +1 -0
  41. package/lib/typescript/figma/Textarea.figma.d.ts +8 -0
  42. package/lib/typescript/figma/Textarea.figma.d.ts.map +1 -0
  43. package/package.json +4 -4
  44. package/src/components/CLAUDE.md +2 -1
  45. package/src/components/Input/styles.ts +6 -3
  46. package/src/components/Select/styles.ts +8 -4
  47. package/src/components/Textarea/index.tsx +179 -0
  48. package/src/components/Textarea/styles.ts +86 -0
  49. package/src/components/index.ts +1 -0
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+
3
+ import { forwardRef, useEffect, useState } from 'react';
4
+ import { Platform } from 'react-native';
5
+ import { InputField as InputFieldPrimitive, InputRoot as InputRootPrimitive, dataAttributes } from '@cdx-ui/primitives';
6
+ import { cn, composeEventHandlers } from '@cdx-ui/utils';
7
+ import { textareaFieldPlaceholderVariants, textareaFieldVariants, textareaRootVariants } from './styles';
8
+
9
+ // Initial/minimum visible rows. Web textareas render compactly, so a smaller default
10
+ // reads better there; native has no intrinsic multiline height, so it needs more.
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+ const DEFAULT_MIN_ROWS = Platform.select({
13
+ web: 2,
14
+ default: 8
15
+ });
16
+
17
+ // Explicit per-size line height (px) set on the field so `rows * lineHeight` maps to an
18
+ // exact pixel height on native. Values track the field font sizes in `styles.ts`.
19
+ const LINE_HEIGHT_BY_SIZE = {
20
+ default: 20,
21
+ small: 16
22
+ };
23
+
24
+ // Module-scoped latch so the dev conflict warning fires at most once per session.
25
+ let hasWarnedResizeAutoGrowConflict = false;
26
+ export const Textarea = /*#__PURE__*/forwardRef(({
27
+ variant = 'outline',
28
+ size = 'default',
29
+ isDisabled,
30
+ isInvalid,
31
+ isReadOnly,
32
+ isRequired,
33
+ isFocused,
34
+ isHovered,
35
+ isFullWidth,
36
+ className,
37
+ placeholderTextColorClassName,
38
+ style,
39
+ numberOfLines,
40
+ autoGrow = false,
41
+ maxRows,
42
+ resize = 'none',
43
+ onContentSizeChange,
44
+ ...rest
45
+ }, ref) => {
46
+ const minRows = numberOfLines ?? DEFAULT_MIN_ROWS;
47
+ const lineHeight = LINE_HEIGHT_BY_SIZE[size ?? 'default'];
48
+ const minHeight = minRows * lineHeight;
49
+ const maxHeight = maxRows != null ? maxRows * lineHeight : undefined;
50
+ const isWeb = Platform.OS === 'web';
51
+ // Web user-resize wins over auto-grow; the two are mutually exclusive.
52
+ const userResizable = isWeb && resize === 'vertical';
53
+ const effectiveAutoGrow = autoGrow && !userResizable;
54
+ useEffect(() => {
55
+ if (__DEV__ && autoGrow && resize === 'vertical' && !hasWarnedResizeAutoGrowConflict) {
56
+ hasWarnedResizeAutoGrowConflict = true;
57
+ console.warn('[Textarea] `autoGrow` and `resize="vertical"` are mutually exclusive. ' + '`resize` takes precedence and `autoGrow` is ignored.');
58
+ }
59
+ }, [autoGrow, resize]);
60
+
61
+ // Native auto-grow: track the measured content height so we can enable internal
62
+ // scrolling once it passes the `maxRows` cap. Growth itself is handled natively
63
+ // (see `nativeScrollEnabled`), not by pinning a height here.
64
+ const [measuredHeight, setMeasuredHeight] = useState(undefined);
65
+ const handleContentSizeChange = event => {
66
+ if (!isWeb && effectiveAutoGrow) {
67
+ setMeasuredHeight(event.nativeEvent.contentSize.height);
68
+ }
69
+ };
70
+
71
+ // On native, a multiline TextInput only grows to fit its content when scrolling is
72
+ // disabled — an explicit height or an enabled scroll view pins it. So for auto-grow we
73
+ // keep `scrollEnabled` off (letting the view size itself between min/max) and only turn
74
+ // scrolling back on once the content exceeds the `maxRows` cap. Undefined elsewhere
75
+ // (web + fixed height) leaves React Native's default (`true`) so overflow scrolls.
76
+ const nativeScrollEnabled = !isWeb && effectiveAutoGrow ? maxHeight != null && measuredHeight != null && measuredHeight > maxHeight : undefined;
77
+
78
+ // Auto-grow (web + native) and fixed sizing all bound the field with min/max height and
79
+ // never pin an explicit `height`: web grows via `field-sizing: content`, native grows via
80
+ // the disabled scroll view above, and the fixed case simply floors at `minHeight`.
81
+ const heightStyle = !isWeb && !effectiveAutoGrow ? {
82
+ minHeight
83
+ } : {
84
+ minHeight,
85
+ maxHeight
86
+ };
87
+
88
+ // `textAlignVertical` is set in style (not just the prop) so it overrides the Android
89
+ // primitive's `center` default — style wins over the deprecated prop.
90
+ const fieldStyle = {
91
+ lineHeight,
92
+ textAlignVertical: 'top',
93
+ ...heightStyle
94
+ };
95
+
96
+ // `className` applies to the root (the visible bordered box), matching the flat
97
+ // CurrencyInput pattern. Field-level utilities below are internal sizing concerns.
98
+ const fieldClassName = cn(textareaFieldVariants({
99
+ size
100
+ }), effectiveAutoGrow && 'web:[field-sizing:content]', userResizable ? 'web:[resize:vertical]' : 'web:[resize:none]');
101
+ return /*#__PURE__*/_jsx(InputRootPrimitive, {
102
+ isDisabled: isDisabled,
103
+ isInvalid: isInvalid,
104
+ isReadOnly: isReadOnly,
105
+ isRequired: isRequired,
106
+ isFocused: isFocused,
107
+ isHovered: isHovered,
108
+ isFullWidth: isFullWidth,
109
+ className: cn(textareaRootVariants({
110
+ variant,
111
+ size
112
+ }), className),
113
+ style: style,
114
+ ...dataAttributes({
115
+ slot: 'textarea'
116
+ }),
117
+ children: /*#__PURE__*/_jsx(InputFieldPrimitive, {
118
+ ref: ref,
119
+ placeholderTextColorClassName: cn(textareaFieldPlaceholderVariants(), placeholderTextColorClassName),
120
+ ...rest,
121
+ multiline: true,
122
+ numberOfLines: isWeb ? minRows : undefined,
123
+ textAlignVertical: "top",
124
+ scrollEnabled: nativeScrollEnabled,
125
+ className: fieldClassName,
126
+ style: fieldStyle,
127
+ onContentSizeChange: composeEventHandlers(onContentSizeChange, handleContentSizeChange)
128
+ })
129
+ });
130
+ });
131
+ Textarea.displayName = 'Textarea';
132
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["forwardRef","useEffect","useState","Platform","InputField","InputFieldPrimitive","InputRoot","InputRootPrimitive","dataAttributes","cn","composeEventHandlers","textareaFieldPlaceholderVariants","textareaFieldVariants","textareaRootVariants","jsx","_jsx","DEFAULT_MIN_ROWS","select","web","default","LINE_HEIGHT_BY_SIZE","small","hasWarnedResizeAutoGrowConflict","Textarea","variant","size","isDisabled","isInvalid","isReadOnly","isRequired","isFocused","isHovered","isFullWidth","className","placeholderTextColorClassName","style","numberOfLines","autoGrow","maxRows","resize","onContentSizeChange","rest","ref","minRows","lineHeight","minHeight","maxHeight","undefined","isWeb","OS","userResizable","effectiveAutoGrow","__DEV__","console","warn","measuredHeight","setMeasuredHeight","handleContentSizeChange","event","nativeEvent","contentSize","height","nativeScrollEnabled","heightStyle","fieldStyle","textAlignVertical","fieldClassName","slot","children","multiline","scrollEnabled","displayName"],"sourceRoot":"../../../../src","sources":["components/Textarea/index.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ import { cva } from 'class-variance-authority';
4
+ import { DISABLED_CURSOR, TRANSITION_COLORS } from '../../styles/primitives';
5
+ export const textareaRootVariants = cva([
6
+ // Multiline shell: stretch the field to full width and let the shell grow with it
7
+ // (no fixed height, no overflow-hidden so a web resize handle is never clipped).
8
+ 'w-full flex-row items-stretch', 'bg-surface-primary', 'border-solid border-stroke-primary', 'web:border-default native:border-[length:var(--border-width-default)]', 'rounded-[var(--border-radius-default)]', TRANSITION_COLORS, 'data-[disabled=true]:bg-surface-secondary', 'data-[disabled=true]:opacity-[var(--opacity-disabled)]', DISABLED_CURSOR, 'data-[readonly=true]:cursor-default', 'data-[readonly=true]:bg-surface-secondary', 'web:data-[hover=true]:data-[focus=false]:data-[invalid=false]:border-stroke-hover',
9
+ // Web: inset ring avoids a border-width change so the shell never shifts on focus.
10
+ // Recolor the border to match the ring so the two read as a single focus outline
11
+ // instead of a gray border + colored ring.
12
+ 'web:data-[focus=true]:ring-inset', 'web:data-[focus=true]:ring-[length:var(--border-width-focused)]', 'web:data-[focus=true]:data-[invalid=false]:ring-stroke-action', 'web:data-[focus=true]:data-[invalid=false]:border-stroke-action', 'web:data-[focus=true]:data-[invalid=true]:ring-stroke-danger', 'web:data-[focus=true]:data-[invalid=true]:border-stroke-danger',
13
+ // Native: thicker border on focus; size variants subtract a hairline of padding
14
+ // so layout doesn't shift by 1px.
15
+ 'native:data-[focus=true]:border-[length:var(--border-width-focused)]', 'native:data-[field-state=focused]:border-stroke-action', 'native:data-[field-state=focused-invalid]:border-stroke-danger', 'data-[invalid=true]:border-stroke-danger'], {
16
+ variants: {
17
+ variant: {
18
+ outline: []
19
+ },
20
+ size: {
21
+ default: ['px-4 py-3 gap-4', 'native:data-[focus=true]:px-[calc(var(--spacing-4)-var(--spacing-px))]', 'native:data-[focus=true]:py-[calc(var(--spacing-3)-var(--spacing-px))]'],
22
+ small: ['px-3 py-2 gap-1.5', 'native:data-[focus=true]:px-[calc(var(--spacing-3)-var(--spacing-px))]', 'native:data-[focus=true]:py-[calc(var(--spacing-2)-var(--spacing-px))]']
23
+ }
24
+ },
25
+ defaultVariants: {
26
+ variant: 'outline',
27
+ size: 'default'
28
+ }
29
+ });
30
+ export const textareaFieldVariants = cva([
31
+ // `min-w-0` lets the field shrink below its intrinsic content width so the shell
32
+ // never overflows (mirrors the Input field rationale).
33
+ 'flex-1 min-w-0 bg-transparent p-0', 'text-content-primary', 'placeholder:text-content-tertiary', 'web:outline-none', 'tracking-normal'], {
34
+ variants: {
35
+ size: {
36
+ default: 'text-[0.875rem]',
37
+ small: 'text-[0.75rem]'
38
+ }
39
+ },
40
+ defaultVariants: {
41
+ size: 'default'
42
+ }
43
+ });
44
+ export const textareaFieldPlaceholderVariants = cva(['accent-content-tertiary']);
45
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["cva","DISABLED_CURSOR","TRANSITION_COLORS","textareaRootVariants","variants","variant","outline","size","default","small","defaultVariants","textareaFieldVariants","textareaFieldPlaceholderVariants"],"sourceRoot":"../../../../src","sources":["components/Textarea/styles.ts"],"mappings":";;AAAA,SAASA,GAAG,QAA2B,0BAA0B;AACjE,SAASC,eAAe,EAAEC,iBAAiB,QAAQ,yBAAyB;AAE5E,OAAO,MAAMC,oBAAoB,GAAGH,GAAG,CACrC;AACE;AACA;AACA,+BAA+B,EAC/B,oBAAoB,EACpB,oCAAoC,EACpC,uEAAuE,EACvE,wCAAwC,EACxCE,iBAAiB,EACjB,2CAA2C,EAC3C,wDAAwD,EACxDD,eAAe,EACf,qCAAqC,EACrC,2CAA2C,EAC3C,mFAAmF;AACnF;AACA;AACA;AACA,kCAAkC,EAClC,iEAAiE,EACjE,+DAA+D,EAC/D,iEAAiE,EACjE,8DAA8D,EAC9D,gEAAgE;AAChE;AACA;AACA,sEAAsE,EACtE,wDAAwD,EACxD,gEAAgE,EAChE,0CAA0C,CAC3C,EACD;EACEG,QAAQ,EAAE;IACRC,OAAO,EAAE;MACPC,OAAO,EAAE;IACX,CAAC;IACDC,IAAI,EAAE;MACJC,OAAO,EAAE,CACP,iBAAiB,EACjB,wEAAwE,EACxE,wEAAwE,CACzE;MACDC,KAAK,EAAE,CACL,mBAAmB,EACnB,wEAAwE,EACxE,wEAAwE;IAE5E;EACF,CAAC;EACDC,eAAe,EAAE;IACfL,OAAO,EAAE,SAAS;IAClBE,IAAI,EAAE;EACR;AACF,CACF,CAAC;AAED,OAAO,MAAMI,qBAAqB,GAAGX,GAAG,CACtC;AACE;AACA;AACA,mCAAmC,EACnC,sBAAsB,EACtB,mCAAmC,EACnC,kBAAkB,EAClB,iBAAiB,CAClB,EACD;EACEI,QAAQ,EAAE;IACRG,IAAI,EAAE;MACJC,OAAO,EAAE,iBAAiB;MAC1BC,KAAK,EAAE;IACT;EACF,CAAC;EACDC,eAAe,EAAE;IACfH,IAAI,EAAE;EACR;AACF,CACF,CAAC;AAED,OAAO,MAAMK,gCAAgC,GAAGZ,GAAG,CAAC,CAAC,yBAAyB,CAAC,CAAC","ignoreList":[]}
@@ -27,6 +27,7 @@ export * from './ScopedTheme';
27
27
  export * from './Select';
28
28
  export * from './VirtualizedList';
29
29
  export * from './Switch';
30
+ export * from './Textarea';
30
31
  export * from './Tile';
31
32
  export * from './Toast';
32
33
  export { HStack, VStack } from './Stack';
@@ -1 +1 @@
1
- {"version":3,"names":["HStack","VStack"],"sourceRoot":"../../../src","sources":["components/index.ts"],"mappings":";;AAAA,cAAc,SAAS;AACvB,cAAc,eAAe;AAC7B,cAAc,UAAU;AACxB,cAAc,eAAe;AAC7B,cAAc,OAAO;AACrB,cAAc,UAAU;AACxB,cAAc,QAAQ;AACtB,cAAc,YAAY;AAC1B,cAAc,QAAQ;AACtB,cAAc,iBAAiB;AAC/B,cAAc,UAAU;AACxB,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,QAAQ;AACtB,cAAc,SAAS;AACvB,cAAc,SAAS;AACvB,cAAc,YAAY;AAC1B,cAAc,QAAQ;AACtB,cAAc,YAAY;AAC1B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,qBAAqB;AACnC,cAAc,SAAS;AACvB,cAAc,eAAe;AAC7B,cAAc,UAAU;AACxB,cAAc,mBAAmB;AACjC,cAAc,UAAU;AACxB,cAAc,QAAQ;AACtB,cAAc,SAAS;AACvB,SAASA,MAAM,EAAEC,MAAM,QAAQ,SAAS;AACxC,cAAc,WAAW;AACzB,cAAc,QAAQ;AACtB,cAAc,QAAQ;AACtB,cAAc,cAAc;AAC5B,cAAc,qBAAqB","ignoreList":[]}
1
+ {"version":3,"names":["HStack","VStack"],"sourceRoot":"../../../src","sources":["components/index.ts"],"mappings":";;AAAA,cAAc,SAAS;AACvB,cAAc,eAAe;AAC7B,cAAc,UAAU;AACxB,cAAc,eAAe;AAC7B,cAAc,OAAO;AACrB,cAAc,UAAU;AACxB,cAAc,QAAQ;AACtB,cAAc,YAAY;AAC1B,cAAc,QAAQ;AACtB,cAAc,iBAAiB;AAC/B,cAAc,UAAU;AACxB,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,QAAQ;AACtB,cAAc,SAAS;AACvB,cAAc,SAAS;AACvB,cAAc,YAAY;AAC1B,cAAc,QAAQ;AACtB,cAAc,YAAY;AAC1B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,qBAAqB;AACnC,cAAc,SAAS;AACvB,cAAc,eAAe;AAC7B,cAAc,UAAU;AACxB,cAAc,mBAAmB;AACjC,cAAc,UAAU;AACxB,cAAc,YAAY;AAC1B,cAAc,QAAQ;AACtB,cAAc,SAAS;AACvB,SAASA,MAAM,EAAEC,MAAM,QAAQ,SAAS;AACxC,cAAc,WAAW;AACzB,cAAc,QAAQ;AACtB,cAAc,QAAQ;AACtB,cAAc,cAAc;AAC5B,cAAc,qBAAqB","ignoreList":[]}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ // url=https://www.figma.com/design/0lEVMVlLj8ZS4fgItr3pmd/%E2%AD%90-Forge-DS--Components?node-id=7078-1839
4
+ // source=packages/components/src/components/Field/index.tsx
5
+ // component=Field
6
+ import figma from 'figma';
7
+ const instance = figma.selectedInstance;
8
+ const showLabel = instance.getBoolean('Show Label?');
9
+ const showHelperText = instance.getBoolean('Show Helper Text?');
10
+ const showErrorText = instance.getBoolean('Show Error Text?');
11
+
12
+ // Enum-as-boolean: isInvalid / isDisabled are VARIANT properties in Figma (string values "true"/"false").
13
+ // Map "false" to undefined so renderProp omits them from the snippet.
14
+ const isInvalid = instance.getEnum('isInvalid', {
15
+ true: true,
16
+ false: undefined
17
+ });
18
+ const isDisabled = instance.getEnum('isDisabled', {
19
+ true: true,
20
+ false: undefined
21
+ });
22
+ const isInvalidProp = figma.helpers.react.renderProp('isInvalid', isInvalid);
23
+ const isDisabledProp = figma.helpers.react.renderProp('isDisabled', isDisabled);
24
+ const labelText = instance.findText('{Label}', {
25
+ traverseInstances: true
26
+ }).textContent;
27
+ const helperText = instance.findText('{HelperText}', {
28
+ traverseInstances: true
29
+ }).textContent;
30
+ const errorText = instance.findText('{ErrorText}', {
31
+ traverseInstances: true
32
+ }).textContent;
33
+ const textarea = instance.findInstance('Textarea');
34
+ let textareaSnippet;
35
+ if (textarea?.type === 'INSTANCE') {
36
+ textareaSnippet = textarea.executeTemplate().example;
37
+ }
38
+ export default {
39
+ id: 'field-textarea',
40
+ // Only import Field here; the nested Textarea template provides its own "import { Textarea } …" line.
41
+ // Code Connect merges the two separate import statements from the same package automatically.
42
+ imports: ["import { Field } from '@cdx-ui/components'"],
43
+ example: figma.code`
44
+ <Field${isInvalidProp}${isDisabledProp}>
45
+ ${showLabel ? figma.code`<Field.Label>${labelText}</Field.Label>` : null}
46
+ ${textareaSnippet}
47
+ ${!isInvalid && showHelperText ? figma.code`<Field.Helper>${helperText}</Field.Helper>` : null}
48
+ ${isInvalid && showErrorText ? figma.code`<Field.Error>${errorText}</Field.Error>` : null}
49
+ </Field>`
50
+ };
51
+ //# sourceMappingURL=Field.Textarea.figma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["figma","instance","selectedInstance","showLabel","getBoolean","showHelperText","showErrorText","isInvalid","getEnum","true","false","undefined","isDisabled","isInvalidProp","helpers","react","renderProp","isDisabledProp","labelText","findText","traverseInstances","textContent","helperText","errorText","textarea","findInstance","textareaSnippet","type","executeTemplate","example","id","imports","code"],"sourceRoot":"../../../src","sources":["figma/Field.Textarea.figma.ts"],"mappings":";;AAAA;AACA;AACA;AACA,OAAOA,KAAK,MAAM,OAAO;AAEzB,MAAMC,QAAQ,GAAGD,KAAK,CAACE,gBAAgB;AAEvC,MAAMC,SAAS,GAAGF,QAAQ,CAACG,UAAU,CAAC,aAAa,CAAC;AACpD,MAAMC,cAAc,GAAGJ,QAAQ,CAACG,UAAU,CAAC,mBAAmB,CAAC;AAC/D,MAAME,aAAa,GAAGL,QAAQ,CAACG,UAAU,CAAC,kBAAkB,CAAC;;AAE7D;AACA;AACA,MAAMG,SAAS,GAAGN,QAAQ,CAACO,OAAO,CAAC,WAAW,EAAE;EAC9CC,IAAI,EAAE,IAAI;EACVC,KAAK,EAAEC;AACT,CAAC,CAAC;AACF,MAAMC,UAAU,GAAGX,QAAQ,CAACO,OAAO,CAAC,YAAY,EAAE;EAChDC,IAAI,EAAE,IAAI;EACVC,KAAK,EAAEC;AACT,CAAC,CAAC;AAEF,MAAME,aAAa,GAAGb,KAAK,CAACc,OAAO,CAACC,KAAK,CAACC,UAAU,CAAC,WAAW,EAAET,SAAS,CAAC;AAC5E,MAAMU,cAAc,GAAGjB,KAAK,CAACc,OAAO,CAACC,KAAK,CAACC,UAAU,CAAC,YAAY,EAAEJ,UAAU,CAAC;AAE/E,MAAMM,SAAS,GACbjB,QAAQ,CAACkB,QAAQ,CAAC,SAAS,EAAE;EAC3BC,iBAAiB,EAAE;AACrB,CAAC,CAAC,CACFC,WAAW;AACb,MAAMC,UAAU,GACdrB,QAAQ,CAACkB,QAAQ,CAAC,cAAc,EAAE;EAChCC,iBAAiB,EAAE;AACrB,CAAC,CAAC,CACFC,WAAW;AACb,MAAME,SAAS,GACbtB,QAAQ,CAACkB,QAAQ,CAAC,aAAa,EAAE;EAC/BC,iBAAiB,EAAE;AACrB,CAAC,CAAC,CACFC,WAAW;AAEb,MAAMG,QAAQ,GAAGvB,QAAQ,CAACwB,YAAY,CAAC,UAAU,CAAC;AAClD,IAAIC,eAA4D;AAChE,IAAIF,QAAQ,EAAEG,IAAI,KAAK,UAAU,EAAE;EACjCD,eAAe,GAAGF,QAAQ,CAACI,eAAe,CAAC,CAAC,CAACC,OAAO;AACtD;AAEA,eAAe;EACbC,EAAE,EAAE,gBAAgB;EACpB;EACA;EACAC,OAAO,EAAE,CAAC,4CAA4C,CAAC;EACvDF,OAAO,EAAE7B,KAAK,CAACgC,IAAI;AACrB,QAAQnB,aAAa,GAAGI,cAAc;AACtC,IAAId,SAAS,GAAGH,KAAK,CAACgC,IAAI,gBAAgBd,SAAS,gBAAgB,GAAG,IAAI;AAC1E,IAAIQ,eAAe;AACnB,IAAI,CAACnB,SAAS,IAAIF,cAAc,GAAGL,KAAK,CAACgC,IAAI,iBAAiBV,UAAU,iBAAiB,GAAG,IAAI;AAChG,IAAIf,SAAS,IAAID,aAAa,GAAGN,KAAK,CAACgC,IAAI,gBAAgBT,SAAS,gBAAgB,GAAG,IAAI;AAC3F;AACA,CAAC","ignoreList":[]}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ // url=https://www.figma.com/design/0lEVMVlLj8ZS4fgItr3pmd/%E2%AD%90-Forge-DS--Components?node-id=7078-1235
4
+ // source=packages/components/src/components/Textarea/index.tsx
5
+ // component=Textarea
6
+ import figma from 'figma';
7
+ const instance = figma.selectedInstance;
8
+ const variant = instance.getEnum('variant', {
9
+ outlined: 'outline'
10
+ });
11
+ const isInvalid = instance.getEnum('isInvalid', {
12
+ true: true,
13
+ false: undefined
14
+ });
15
+ const isDisabled = instance.getEnum('isDisabled', {
16
+ true: true,
17
+ false: undefined
18
+ });
19
+ const isInvalidProp = figma.helpers.react.renderProp('isInvalid', isInvalid);
20
+ const isDisabledProp = figma.helpers.react.renderProp('isDisabled', isDisabled);
21
+ const showValue = instance.getEnum('Show Value?', {
22
+ true: true,
23
+ false: false
24
+ });
25
+ const showPlaceholder = instance.getEnum('Show Placeholder?', {
26
+ true: true,
27
+ false: false
28
+ });
29
+ const valueText = instance.findText('{value}', {
30
+ traverseInstances: true
31
+ }).textContent;
32
+ const placeholder = instance.getString('placeholder');
33
+ const defaultValueProp = figma.helpers.react.renderProp('defaultValue', showValue ? valueText : undefined);
34
+ const placeholderProp = figma.helpers.react.renderProp('placeholder', showPlaceholder ? placeholder : undefined);
35
+ export default {
36
+ id: 'textarea',
37
+ imports: ["import { Textarea } from '@cdx-ui/components'"],
38
+ example: figma.code`
39
+ <Textarea variant="${variant}" ${isInvalidProp}${isDisabledProp}${defaultValueProp}${placeholderProp} />`
40
+ };
41
+ //# sourceMappingURL=Textarea.figma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["figma","instance","selectedInstance","variant","getEnum","outlined","isInvalid","true","false","undefined","isDisabled","isInvalidProp","helpers","react","renderProp","isDisabledProp","showValue","showPlaceholder","valueText","findText","traverseInstances","textContent","placeholder","getString","defaultValueProp","placeholderProp","id","imports","example","code"],"sourceRoot":"../../../src","sources":["figma/Textarea.figma.ts"],"mappings":";;AAAA;AACA;AACA;AACA,OAAOA,KAAK,MAAM,OAAO;AAEzB,MAAMC,QAAQ,GAAGD,KAAK,CAACE,gBAAgB;AAEvC,MAAMC,OAAO,GAAGF,QAAQ,CAACG,OAAO,CAAC,SAAS,EAAE;EAC1CC,QAAQ,EAAE;AACZ,CAAC,CAAC;AAEF,MAAMC,SAAS,GAAGL,QAAQ,CAACG,OAAO,CAAC,WAAW,EAAE;EAC9CG,IAAI,EAAE,IAAI;EACVC,KAAK,EAAEC;AACT,CAAC,CAAC;AACF,MAAMC,UAAU,GAAGT,QAAQ,CAACG,OAAO,CAAC,YAAY,EAAE;EAChDG,IAAI,EAAE,IAAI;EACVC,KAAK,EAAEC;AACT,CAAC,CAAC;AAEF,MAAME,aAAa,GAAGX,KAAK,CAACY,OAAO,CAACC,KAAK,CAACC,UAAU,CAAC,WAAW,EAAER,SAAS,CAAC;AAC5E,MAAMS,cAAc,GAAGf,KAAK,CAACY,OAAO,CAACC,KAAK,CAACC,UAAU,CAAC,YAAY,EAAEJ,UAAU,CAAC;AAE/E,MAAMM,SAAS,GAAGf,QAAQ,CAACG,OAAO,CAAC,aAAa,EAAE;EAChDG,IAAI,EAAE,IAAI;EACVC,KAAK,EAAE;AACT,CAAC,CAAC;AACF,MAAMS,eAAe,GAAGhB,QAAQ,CAACG,OAAO,CAAC,mBAAmB,EAAE;EAC5DG,IAAI,EAAE,IAAI;EACVC,KAAK,EAAE;AACT,CAAC,CAAC;AAEF,MAAMU,SAAS,GACbjB,QAAQ,CAACkB,QAAQ,CAAC,SAAS,EAAE;EAC3BC,iBAAiB,EAAE;AACrB,CAAC,CAAC,CACFC,WAAW;AACb,MAAMC,WAAW,GAAGrB,QAAQ,CAACsB,SAAS,CAAC,aAAa,CAAC;AAErD,MAAMC,gBAAgB,GAAGxB,KAAK,CAACY,OAAO,CAACC,KAAK,CAACC,UAAU,CACrD,cAAc,EACdE,SAAS,GAAGE,SAAS,GAAGT,SAC1B,CAAC;AACD,MAAMgB,eAAe,GAAGzB,KAAK,CAACY,OAAO,CAACC,KAAK,CAACC,UAAU,CACpD,aAAa,EACbG,eAAe,GAAGK,WAAW,GAAGb,SAClC,CAAC;AAED,eAAe;EACbiB,EAAE,EAAE,UAAU;EACdC,OAAO,EAAE,CAAC,+CAA+C,CAAC;EAC1DC,OAAO,EAAE5B,KAAK,CAAC6B,IAAI;AACrB,qBAAqB1B,OAAO,KAAKQ,aAAa,GAAGI,cAAc,GAAGS,gBAAgB,GAAGC,eAAe;AACpG,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/Input/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,eAAO,MAAM,iBAAiB;;;8EAkD7B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;8EAyB9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,oFAA4D,CAAC;AAE3F,eAAO,MAAM,iBAAiB;;8EAU5B,CAAC;AAEH,eAAO,MAAM,6BAA6B,oFAAmC,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG,YAAY,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/Input/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,eAAO,MAAM,iBAAiB;;;8EAqD7B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;8EAyB9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,oFAA4D,CAAC;AAE3F,eAAO,MAAM,iBAAiB;;8EAU5B,CAAC;AAEH,eAAO,MAAM,6BAA6B,oFAAmC,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG,YAAY,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/Select/styles.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,eAAO,MAAM,qBAAqB;;;8EA2DjC,CAAC;AAIF,eAAO,MAAM,mBAAmB;;8EAkB/B,CAAC;AAIF,eAAO,MAAM,kBAAkB;;8EAiB9B,CAAC;AAIF,eAAO,MAAM,qBAAqB,oFAWhC,CAAC;AAIH,eAAO,MAAM,kBAAkB;;8EAsB9B,CAAC;AAIF,eAAO,MAAM,uBAAuB;;8EAanC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/Select/styles.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,eAAO,MAAM,qBAAqB;;;8EA+DjC,CAAC;AAIF,eAAO,MAAM,mBAAmB;;8EAkB/B,CAAC;AAIF,eAAO,MAAM,kBAAkB;;8EAiB9B,CAAC;AAIF,eAAO,MAAM,qBAAqB,oFAWhC,CAAC;AAIH,eAAO,MAAM,kBAAkB;;8EAsB9B,CAAC;AAIF,eAAO,MAAM,uBAAuB;;8EAanC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { type TextInput, type TextInputProps, type ViewProps } from 'react-native';
2
+ import { type IInputFieldProps } from '@cdx-ui/primitives';
3
+ import { type TextareaVariantProps } from './styles';
4
+ export type TextareaResize = 'none' | 'vertical';
5
+ export interface TextareaProps extends Omit<TextInputProps, 'multiline' | 'children' | 'style'>, IInputFieldProps, TextareaVariantProps {
6
+ className?: string;
7
+ placeholderTextColorClassName?: string;
8
+ /** Initial / minimum visible rows. Defaults to 2 on web and 8 on native. */
9
+ numberOfLines?: number;
10
+ /**
11
+ * Grow the field height to fit its content. Defaults to `false`.
12
+ * Web uses `field-sizing: content`; native measures via `onContentSizeChange`.
13
+ */
14
+ autoGrow?: boolean;
15
+ /** Caps `autoGrow` at this many rows, after which the field scrolls. */
16
+ maxRows?: number;
17
+ /**
18
+ * Web-only user resize affordance. Defaults to `'none'`. `'vertical'` exposes the
19
+ * browser resize handle and takes precedence over `autoGrow` (they are mutually
20
+ * exclusive). No-op on native.
21
+ */
22
+ resize?: TextareaResize;
23
+ style?: ViewProps['style'];
24
+ }
25
+ export declare const Textarea: import("react").ForwardRefExoticComponent<TextareaProps & import("react").RefAttributes<TextInput>>;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Textarea/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,cAAc,EAEnB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,KAAK,oBAAoB,EAI1B,MAAM,UAAU,CAAC;AAelB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjD,MAAM,WAAW,aACf,SACE,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,EACxD,gBAAgB,EAChB,oBAAoB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;CAC5B;AAED,eAAO,MAAM,QAAQ,qGAkHpB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ export declare const textareaRootVariants: (props?: ({
3
+ variant?: "outline" | null | undefined;
4
+ size?: "small" | "default" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export declare const textareaFieldVariants: (props?: ({
7
+ size?: "small" | "default" | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ export declare const textareaFieldPlaceholderVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
10
+ export type TextareaVariantProps = VariantProps<typeof textareaRootVariants>;
11
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/Textarea/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,eAAO,MAAM,oBAAoB;;;8EAuDhC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;8EAqBjC,CAAC;AAEF,eAAO,MAAM,gCAAgC,oFAAmC,CAAC;AAEjF,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -25,6 +25,7 @@ export * from './ScopedTheme';
25
25
  export * from './Select';
26
26
  export * from './VirtualizedList';
27
27
  export * from './Switch';
28
+ export * from './Textarea';
28
29
  export * from './Tile';
29
30
  export * from './Toast';
30
31
  export { HStack, VStack } from './Stack';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import figma from 'figma';
2
+ declare const _default: {
3
+ id: string;
4
+ imports: string[];
5
+ example: figma.TemplateStringResult;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=Field.Textarea.figma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Field.Textarea.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Field.Textarea.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;AA4C1B,wBAYE"}
@@ -0,0 +1,8 @@
1
+ import figma from 'figma';
2
+ declare const _default: {
3
+ id: string;
4
+ imports: string[];
5
+ example: figma.TemplateStringResult;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=Textarea.figma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Textarea.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Textarea.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;AA6C1B,wBAKE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdx-ui/components",
3
- "version": "0.0.1-beta.90",
3
+ "version": "0.0.1-beta.92",
4
4
  "main": "lib/commonjs/index.js",
5
5
  "module": "lib/module/index.js",
6
6
  "react-native": "src/index.ts",
@@ -67,9 +67,9 @@
67
67
  "@gorhom/bottom-sheet": "^5.2.6",
68
68
  "class-variance-authority": "^0.7.1",
69
69
  "uniwind": "1.10.0",
70
- "@cdx-ui/primitives": "0.0.1-beta.90",
71
- "@cdx-ui/utils": "0.0.1-beta.90",
72
- "@cdx-ui/icons": "0.0.1-beta.90"
70
+ "@cdx-ui/primitives": "0.0.1-beta.92",
71
+ "@cdx-ui/utils": "0.0.1-beta.92",
72
+ "@cdx-ui/icons": "0.0.1-beta.92"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@react-navigation/bottom-tabs": "*",
@@ -68,6 +68,7 @@ Variant functions take only static design inputs (`variant`/`color`/`size`/`full
68
68
  - CSS-layer state changes are free of React work: when the primitive flips `data-hover=true`, the CSS engine (web) and Uniwind's native style layer reconcile styles without re-rendering React, re-running CVA, or invoking `cn()`/`tailwind-merge`.
69
69
  - Variant-input state changes cascade React work: CVA re-runs, `cn()` re-merges, and className-prop reconciliation cascades through the tree.
70
70
  - Sub-slots can react to root state via parent selectors (`data-[hover=true]:`) without each slot subscribing to context (per Standard 1).
71
+ - **Native compound conditions** — on native, prefer single-condition `data-[field-state=...]` selectors backed by a primitive-derived compound-state attribute over compound `data-[]:data-[]` chains (Uniwind matches only the last condition). Web may keep compound chains. See `Input/styles.ts` and `Select/styles.ts`; full practice in `docs/internal/practices/data-attributes.md` § "Compound state on native".
71
72
 
72
73
  ### Standard 6 — Position hints (`data-icon="inline-start|inline-end"`)
73
74
 
@@ -181,7 +182,7 @@ export type ComponentVariantProps = VariantProps<typeof componentRootVariants>;
181
182
  ### Key rules
182
183
 
183
184
  - **Semantic token classes only** — use `bg-surface-action-strong`, `text-content-primary`, `border-stroke-primary`, etc. Never hardcode hex colors, `bg-white`, `text-black`, or raw Tailwind color scales for themed values.
184
- - **`data-[state]` selectors** — use `data-[disabled=true]:`, `data-[hover=true]:`, `data-[active=true]:`, `data-[focus-visible=true]:` for interaction states. Primitives emit these data attributes (Standard 1). **Interaction state is never a CVA variant input** (Standard 5).
185
+ - **`data-[state]` selectors** — use `data-[disabled=true]:`, `data-[hover=true]:`, `data-[active=true]:`, `data-[focus-visible=true]:` for interaction states. Primitives emit these data attributes (Standard 1). **Interaction state is never a CVA variant input** (Standard 5). On native, prefer single-condition `data-[field-state=...]` selectors backed by a primitive-derived compound-state attribute over compound `data-[]:data-[]` chains (which only match the last condition); web may keep compound chains. See `Input/styles.ts` / `Select/styles.ts`.
185
186
  - **`data-[icon=inline-start|inline-end]` selectors** for icon/spinner position spacing (Standard 6) — pair with logical-property utilities (`me-*`/`ms-*`) so RTL flips automatically.
186
187
  - **`Platform.select()`** for platform-specific classes — web gets `data-[hover=true]` styles (hover exists on web); native responds only to `data-[active=true]` (press). Always set `default` (native) and `web` keys.
187
188
  - **Shared style primitives** — import `DISABLED_CURSOR`, `TRANSITION_COLORS`, etc. from `../../styles/primitives` for cross-component consistency.
@@ -16,16 +16,19 @@ export const inputRootVariants = cva(
16
16
  'data-[readonly=true]:bg-surface-secondary',
17
17
  'web:data-[hover=true]:data-[focus=false]:data-[invalid=false]:border-stroke-hover',
18
18
  // Web: inset ring avoids a border-width change so the shell never shifts on focus and
19
- // no per-size padding compensation is required.
19
+ // no per-size padding compensation is required. Recolor the border to match the ring so
20
+ // the two read as a single focus outline instead of a gray border + colored ring.
20
21
  'web:data-[focus=true]:ring-inset',
21
22
  'web:data-[focus=true]:ring-[length:var(--border-width-focused)]',
22
23
  'web:data-[focus=true]:data-[invalid=false]:ring-stroke-action',
24
+ 'web:data-[focus=true]:data-[invalid=false]:border-stroke-action',
23
25
  'web:data-[focus=true]:data-[invalid=true]:ring-stroke-danger',
26
+ 'web:data-[focus=true]:data-[invalid=true]:border-stroke-danger',
24
27
  // Native: thicker border on focus; size variants below subtract a hairline of padding
25
28
  // so layout doesn't shift by 1px.
26
29
  'native:data-[focus=true]:border-[length:var(--border-width-focused)]',
27
- 'native:data-[focus=true]:data-[invalid=false]:border-stroke-action',
28
- 'native:data-[focus=true]:data-[invalid=true]:border-stroke-danger',
30
+ 'native:data-[field-state=focused]:border-stroke-action',
31
+ 'native:data-[field-state=focused-invalid]:border-stroke-danger',
29
32
  'data-[invalid=true]:border-stroke-danger',
30
33
  ],
31
34
  {
@@ -18,21 +18,25 @@ export const selectTriggerVariants = cva(
18
18
  'data-[readonly=true]:bg-surface-secondary',
19
19
  'web:data-[hover=true]:data-[focus=false]:data-[invalid=false]:border-stroke-hover',
20
20
  // Web: inset ring avoids a border-width change so no padding compensation is needed.
21
+ // Recolor the border to match the ring so the two read as a single focus outline
22
+ // instead of a gray border + colored ring.
21
23
  'web:data-[focus=true]:ring-inset',
22
24
  'web:data-[focus=true]:ring-[length:var(--border-width-focused)]',
23
25
  'web:data-[focus=true]:data-[invalid=false]:ring-stroke-action',
26
+ 'web:data-[focus=true]:data-[invalid=false]:border-stroke-action',
24
27
  'web:data-[focus=true]:data-[invalid=true]:ring-stroke-danger',
28
+ 'web:data-[focus=true]:data-[invalid=true]:border-stroke-danger',
25
29
  'web:data-[state=open]:ring-inset',
26
30
  'web:data-[state=open]:ring-[length:var(--border-width-focused)]',
27
31
  'web:data-[state=open]:data-[invalid=false]:ring-stroke-action',
32
+ 'web:data-[state=open]:data-[invalid=false]:border-stroke-action',
28
33
  'web:data-[state=open]:data-[invalid=true]:ring-stroke-danger',
34
+ 'web:data-[state=open]:data-[invalid=true]:border-stroke-danger',
29
35
  // Native: thicker border; size variants below compensate the layout shift.
30
36
  'native:data-[focus=true]:border-[length:var(--border-width-focused)]',
31
- 'native:data-[focus=true]:data-[invalid=false]:border-stroke-action',
32
- 'native:data-[focus=true]:data-[invalid=true]:border-stroke-danger',
37
+ 'native:data-[field-state=focused]:border-stroke-action',
38
+ 'native:data-[field-state=focused-invalid]:border-stroke-danger',
33
39
  'native:data-[state=open]:border-[length:var(--border-width-focused)]',
34
- 'native:data-[state=open]:data-[invalid=false]:border-stroke-action',
35
- 'native:data-[state=open]:data-[invalid=true]:border-stroke-danger',
36
40
  'data-[invalid=true]:border-stroke-danger',
37
41
  ],
38
42
  {