@utk09/finra-ui 0.0.2 → 0.0.3

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.
package/README.md CHANGED
@@ -41,29 +41,39 @@ function App() {
41
41
 
42
42
  ### Styled Components
43
43
 
44
- | Component | Description |
45
- | ------------- | -------------------------------------------------------------------------------------------- |
46
- | `Button` | Button with variant (primary/secondary/tertiary) and sentiment (danger/success/warning/info) |
47
- | `IconButton` | Icon-only button with `aria-label` requirement |
48
- | `ButtonGroup` | Groups buttons with merged borders |
49
- | `Input` | Text input with variants, validation states, adornments, and clearable support |
50
- | `Textarea` | Multi-line text input with character count and auto-resize |
51
- | `NumberInput` | Numeric input with increment/decrement buttons |
52
- | `FormField` | Wrapper that wires label, helper text, and error message with a11y attributes |
53
- | `Checkbox` | Custom-styled checkbox with indeterminate support |
54
- | `Switch` | Toggle switch (on/off) |
55
- | `Badge` | Inline status/category label with variant and sentiment |
56
- | `Divider` | Horizontal or vertical separator |
44
+ | Component | Description |
45
+ | -------------- | -------------------------------------------------------------------------------------------- |
46
+ | `Button` | Button with variant (primary/secondary/tertiary) and sentiment (danger/success/warning/info) |
47
+ | `IconButton` | Icon-only button with `aria-label` requirement |
48
+ | `ButtonGroup` | Groups buttons with merged borders |
49
+ | `Input` | Text input with variants, validation states, adornments, and clearable support |
50
+ | `Textarea` | Multi-line text input with character count and auto-resize |
51
+ | `NumberInput` | Numeric input with increment/decrement buttons |
52
+ | `FormField` | Wrapper that wires label, helper text, and error message with a11y attributes |
53
+ | `Checkbox` | Custom-styled checkbox with indeterminate support |
54
+ | `Switch` | Toggle switch (on/off) |
55
+ | `RadioButton` | Radio button for grouped exclusive selection |
56
+ | `Slider` | Range slider with optional label and value display |
57
+ | `PillInput` | Tokenized tag/pill input with keyboard support |
58
+ | `FileDropZone` | Drag-and-drop file upload zone |
59
+ | `Badge` | Inline status/category label with variant and sentiment |
60
+ | `Divider` | Horizontal or vertical separator |
57
61
 
58
62
  ### Unstyled Components
59
63
 
60
- Every styled component has an unstyled base that provides only behavior and accessibility no visual styles. Import from the `/unstyled` entry point:
64
+ Every styled component has an unstyled base that provides only behavior and accessibility - no visual styles. Import from the `/unstyled` entry point:
61
65
 
62
66
  ```tsx
63
- import { ButtonBase, CheckboxBase, SwitchBase } from "@utk09/finra-ui/unstyled";
67
+ import {
68
+ ButtonBase,
69
+ CheckboxBase,
70
+ SwitchBase,
71
+ RadioButtonBase,
72
+ SliderBase,
73
+ } from "@utk09/finra-ui/unstyled";
64
74
  ```
65
75
 
66
- Available: `ButtonBase`, `IconButtonBase`, `InputBase`, `TextareaBase`, `NumberInputBase`, `CheckboxBase`, `SwitchBase`.
76
+ Available: `ButtonBase`, `IconButtonBase`, `InputBase`, `TextareaBase`, `NumberInputBase`, `CheckboxBase`, `SwitchBase`, `RadioButtonBase`, `SliderBase`.
67
77
 
68
78
  ## Features
69
79
 
@@ -79,7 +89,7 @@ Buttons and Badges support three **variants** and four **sentiments** that combi
79
89
 
80
90
  ### Density System
81
91
 
82
- Control spacing globally via a `data-density` attribute on any ancestor element. All components respond automatically no props needed:
92
+ Control spacing globally via a `data-density` attribute on any ancestor element. All components respond automatically - no props needed:
83
93
 
84
94
  ```tsx
85
95
  {
@@ -143,7 +153,7 @@ Every component renders a stable `data-finra-ui` attribute for targeted CSS over
143
153
 
144
154
  ### Zero External Runtime Dependencies
145
155
 
146
- The only runtime dependencies are `clsx` and `class-variance-authority` — no Radix, no Emotion, no runtime CSS-in-JS.
156
+ The only runtime dependencies are `clsx` and `class-variance-authority`.
147
157
 
148
158
  ## Development
149
159
 
@@ -175,8 +185,8 @@ pnpm run typecheck && pnpm run lint && pnpm run test
175
185
  ### Project Structure
176
186
 
177
187
  ```txt
178
- packages/core/ Component library (@utk09/finra-ui)
179
- apps/storybook/ Storybook documentation app
188
+ packages/core/ - Component library (@utk09/finra-ui)
189
+ apps/storybook/ - Storybook documentation app
180
190
  ```
181
191
 
182
192
  ## License
@@ -0,0 +1,73 @@
1
+ import { jsx as c, jsxs as u } from "react/jsx-runtime";
2
+ import { forwardRef as f, isValidElement as p, cloneElement as l, useRef as y, useEffect as m } from "react";
3
+ function B(...e) {
4
+ return (o) => {
5
+ for (const t of e)
6
+ typeof t == "function" ? t(o) : t && typeof t == "object" && (t.current = o);
7
+ };
8
+ }
9
+ function d(e, o) {
10
+ const t = { ...e, ...o };
11
+ for (const n of Object.keys(e)) {
12
+ if (n === "children" || n === "ref") continue;
13
+ const s = e[n], r = o[n];
14
+ typeof s == "function" && typeof r == "function" && (t[n] = (...a) => {
15
+ r(...a), s(...a);
16
+ }), n === "className" && typeof s == "string" && typeof r == "string" && (t[n] = `${s} ${r}`.trim()), n === "style" && typeof s == "object" && typeof r == "object" && (t[n] = { ...s, ...r });
17
+ }
18
+ return t;
19
+ }
20
+ const i = f(
21
+ ({ children: e, ...o }, t) => {
22
+ if (!p(e))
23
+ return null;
24
+ const n = e.props, s = e.ref;
25
+ return l(e, {
26
+ ...d(o, n),
27
+ ref: B(t, s)
28
+ });
29
+ }
30
+ );
31
+ i.displayName = "Slot";
32
+ const b = f(
33
+ ({ asChild: e = !1, ...o }, t) => /* @__PURE__ */ c(e ? i : "button", { ref: t, ...o })
34
+ );
35
+ b.displayName = "ButtonBase";
36
+ const R = f(
37
+ ({ asChild: e = !1, icon: o, children: t, ...n }, s) => /* @__PURE__ */ u(e ? i : "button", { ref: s, ...n, children: [
38
+ o,
39
+ t
40
+ ] })
41
+ );
42
+ R.displayName = "IconButtonBase";
43
+ function h(...e) {
44
+ return (o) => {
45
+ for (const t of e)
46
+ typeof t == "function" ? t(o) : t && typeof t == "object" && (t.current = o);
47
+ };
48
+ }
49
+ const N = f(
50
+ ({ indeterminate: e, ...o }, t) => {
51
+ const n = y(null);
52
+ return m(() => {
53
+ n.current && (n.current.indeterminate = e ?? !1);
54
+ }, [e]), /* @__PURE__ */ c("input", { ref: h(t, n), type: "checkbox", ...o });
55
+ }
56
+ );
57
+ N.displayName = "CheckboxBase";
58
+ const j = f((e, o) => /* @__PURE__ */ c("input", { ref: o, type: "checkbox", role: "switch", ...e }));
59
+ j.displayName = "SwitchBase";
60
+ const x = f((e, o) => /* @__PURE__ */ c("input", { ref: o, type: "radio", ...e }));
61
+ x.displayName = "RadioButtonBase";
62
+ const C = f((e, o) => /* @__PURE__ */ c("input", { ref: o, type: "range", ...e }));
63
+ C.displayName = "SliderBase";
64
+ export {
65
+ b as B,
66
+ N as C,
67
+ R as I,
68
+ x as R,
69
+ j as S,
70
+ C as a,
71
+ i as b
72
+ };
73
+ //# sourceMappingURL=Slider-BXQjDfhb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slider-BXQjDfhb.js","sources":["../src/unstyled/Slot.tsx","../src/unstyled/Button/Button.tsx","../src/unstyled/IconButton/IconButton.tsx","../src/unstyled/Checkbox/Checkbox.tsx","../src/unstyled/Switch/Switch.tsx","../src/unstyled/RadioButton/RadioButton.tsx","../src/unstyled/Slider/Slider.tsx"],"sourcesContent":["import {\n forwardRef,\n isValidElement,\n cloneElement,\n type ReactNode,\n type HTMLAttributes,\n type Ref,\n} from \"react\";\n\nfunction mergeRefs<T>(...refs: (Ref<T> | undefined)[]): Ref<T> {\n return (value: T | null) => {\n for (const ref of refs) {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref && typeof ref === \"object\") {\n (ref as React.RefObject<T | null>).current = value;\n }\n }\n };\n}\n\nfunction mergeProps(\n slotProps: Record<string, unknown>,\n childProps: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...slotProps, ...childProps };\n\n for (const key of Object.keys(slotProps)) {\n if (key === \"children\" || key === \"ref\") continue;\n\n const slotVal = slotProps[key];\n const childVal = childProps[key];\n\n // Merge event handlers\n if (typeof slotVal === \"function\" && typeof childVal === \"function\") {\n merged[key] = (...args: unknown[]) => {\n childVal(...args);\n slotVal(...args);\n };\n }\n\n // Merge className\n if (key === \"className\" && typeof slotVal === \"string\" && typeof childVal === \"string\") {\n merged[key] = `${slotVal} ${childVal}`.trim();\n }\n\n // Merge style\n if (key === \"style\" && typeof slotVal === \"object\" && typeof childVal === \"object\") {\n merged[key] = { ...(slotVal as object), ...(childVal as object) };\n }\n }\n\n return merged;\n}\n\nexport interface SlotProps extends HTMLAttributes<HTMLElement> {\n children?: ReactNode;\n}\n\nexport const Slot = forwardRef<HTMLElement, SlotProps>(\n ({ children, ...slotProps }, forwardedRef) => {\n if (!isValidElement(children)) {\n return null;\n }\n\n const childProps = children.props as Record<string, unknown>;\n const childRef = (children as unknown as { ref?: Ref<HTMLElement> }).ref;\n\n return cloneElement(children, {\n ...mergeProps(slotProps, childProps),\n ref: mergeRefs(forwardedRef, childRef),\n } as Record<string, unknown>);\n },\n);\n\nSlot.displayName = \"Slot\";\n","import { forwardRef, type ButtonHTMLAttributes } from \"react\";\nimport { Slot } from \"../Slot\";\n\nexport interface ButtonBaseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean;\n}\n\nexport const ButtonBase = forwardRef<HTMLButtonElement, ButtonBaseProps>(\n ({ asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n\n return <Comp ref={ref} {...props} />;\n },\n);\n\nButtonBase.displayName = \"ButtonBase\";\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { Slot } from \"../Slot\";\n\nexport interface IconButtonBaseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean;\n icon: ReactNode;\n \"aria-label\": string;\n}\n\nexport const IconButtonBase = forwardRef<HTMLButtonElement, IconButtonBaseProps>(\n ({ asChild = false, icon, children, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp ref={ref} {...props}>\n {icon}\n {children}\n </Comp>\n );\n },\n);\n\nIconButtonBase.displayName = \"IconButtonBase\";\n","import { forwardRef, useEffect, useRef, type InputHTMLAttributes, type Ref } from \"react\";\n\nexport interface CheckboxBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n indeterminate?: boolean;\n}\n\nfunction mergeRefs<T>(...refs: (Ref<T> | undefined)[]): (value: T | null) => void {\n return (value: T | null) => {\n for (const ref of refs) {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref && typeof ref === \"object\") {\n (ref as React.RefObject<T | null>).current = value;\n }\n }\n };\n}\n\nexport const CheckboxBase = forwardRef<HTMLInputElement, CheckboxBaseProps>(\n ({ indeterminate, ...props }, forwardedRef) => {\n const internalRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (internalRef.current) {\n internalRef.current.indeterminate = indeterminate ?? false;\n }\n }, [indeterminate]);\n\n return <input ref={mergeRefs(forwardedRef, internalRef)} type=\"checkbox\" {...props} />;\n },\n);\n\nCheckboxBase.displayName = \"CheckboxBase\";\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\n\nexport interface SwitchBaseProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"role\"\n> {}\n\nexport const SwitchBase = forwardRef<HTMLInputElement, SwitchBaseProps>((props, ref) => {\n return <input ref={ref} type=\"checkbox\" role=\"switch\" {...props} />;\n});\n\nSwitchBase.displayName = \"SwitchBase\";\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\n\nexport interface RadioButtonBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {}\n\nexport const RadioButtonBase = forwardRef<HTMLInputElement, RadioButtonBaseProps>((props, ref) => {\n return <input ref={ref} type=\"radio\" {...props} />;\n});\n\nRadioButtonBase.displayName = \"RadioButtonBase\";\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\n\nexport interface SliderBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {}\n\nexport const SliderBase = forwardRef<HTMLInputElement, SliderBaseProps>((props, ref) => {\n return <input ref={ref} type=\"range\" {...props} />;\n});\n\nSliderBase.displayName = \"SliderBase\";\n"],"names":["mergeRefs","refs","value","ref","mergeProps","slotProps","childProps","merged","key","slotVal","childVal","args","Slot","forwardRef","children","forwardedRef","isValidElement","childRef","cloneElement","ButtonBase","asChild","props","jsx","IconButtonBase","icon","jsxs","CheckboxBase","indeterminate","internalRef","useRef","useEffect","SwitchBase","RadioButtonBase","SliderBase"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ export interface FileDropZoneProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
3
+ /** Called with selected files. */
4
+ onChange?: (files: File[]) => void;
5
+ /** Accepted file types (e.g. ".pdf,.csv" or "image/*"). */
6
+ accept?: string;
7
+ /** Allow multiple file selection. */
8
+ multiple?: boolean;
9
+ /** Disable the component. */
10
+ disabled?: boolean;
11
+ /** Custom content inside the drop zone. */
12
+ children?: ReactNode;
13
+ }
14
+ export declare const FileDropZone: import('react').ForwardRefExoticComponent<FileDropZoneProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,16 @@
1
+ import { HTMLAttributes } from 'react';
2
+ export interface PillInputProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
3
+ /** Current list of pills (controlled). */
4
+ values?: string[];
5
+ /** Called when the pill list changes. */
6
+ onChange?: (values: string[]) => void;
7
+ /** Placeholder shown when no pills and input is empty. */
8
+ placeholder?: string;
9
+ /** Disable the entire component. */
10
+ disabled?: boolean;
11
+ /** Maximum number of pills allowed. */
12
+ maxPills?: number;
13
+ /** Characters that trigger pill creation (default: Enter). */
14
+ delimiters?: string[];
15
+ }
16
+ export declare const PillInput: import('react').ForwardRefExoticComponent<PillInputProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,6 @@
1
+ import { RadioButtonBaseProps } from '../../unstyled/RadioButton/RadioButton';
2
+ export interface RadioButtonProps extends Omit<RadioButtonBaseProps, "className"> {
3
+ label?: string;
4
+ className?: string;
5
+ }
6
+ export declare const RadioButton: import('react').ForwardRefExoticComponent<RadioButtonProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,7 @@
1
+ import { SliderBaseProps } from '../../unstyled/Slider/Slider';
2
+ export interface SliderProps extends Omit<SliderBaseProps, "className"> {
3
+ label?: string;
4
+ showValue?: boolean;
5
+ className?: string;
6
+ }
7
+ export declare const Slider: import('react').ForwardRefExoticComponent<SliderProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -18,6 +18,10 @@ export declare const componentIds: {
18
18
  readonly formFieldError: "form-field-error";
19
19
  readonly checkbox: "checkbox";
20
20
  readonly switch: "switch";
21
+ readonly radioButton: "radio-button";
22
+ readonly slider: "slider";
23
+ readonly pillInput: "pill-input";
24
+ readonly fileDropZone: "file-drop-zone";
21
25
  readonly badge: "badge";
22
26
  readonly divider: "divider";
23
27
  };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,14 @@ export { Checkbox } from './components/Checkbox/Checkbox';
18
18
  export type { CheckboxProps } from './components/Checkbox/Checkbox';
19
19
  export { Switch } from './components/Switch/Switch';
20
20
  export type { SwitchProps } from './components/Switch/Switch';
21
+ export { RadioButton } from './components/RadioButton/RadioButton';
22
+ export type { RadioButtonProps } from './components/RadioButton/RadioButton';
23
+ export { Slider } from './components/Slider/Slider';
24
+ export type { SliderProps } from './components/Slider/Slider';
25
+ export { PillInput } from './components/PillInput/PillInput';
26
+ export type { PillInputProps } from './components/PillInput/PillInput';
27
+ export { FileDropZone } from './components/FileDropZone/FileDropZone';
28
+ export type { FileDropZoneProps } from './components/FileDropZone/FileDropZone';
21
29
  export { Badge } from './components/Badge/Badge';
22
30
  export type { BadgeProps, BadgeSentiment } from './components/Badge/Badge';
23
31
  export { Divider } from './components/Divider/Divider';