@proyecto-viviana/ui 0.2.5 → 0.3.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.
Files changed (71) hide show
  1. package/dist/index.js +210 -557
  2. package/dist/index.js.map +7 -1
  3. package/dist/index.ssr.js +42 -399
  4. package/dist/index.ssr.js.map +7 -1
  5. package/dist/radio/index.d.ts +27 -12
  6. package/dist/radio/index.d.ts.map +1 -1
  7. package/package.json +11 -12
  8. package/src/alert/index.tsx +0 -48
  9. package/src/assets/favicon.png +0 -0
  10. package/src/assets/fire.gif +0 -0
  11. package/src/autocomplete/index.tsx +0 -313
  12. package/src/avatar/index.tsx +0 -75
  13. package/src/badge/index.tsx +0 -43
  14. package/src/breadcrumbs/index.tsx +0 -207
  15. package/src/button/Button.tsx +0 -74
  16. package/src/button/index.ts +0 -2
  17. package/src/button/types.ts +0 -24
  18. package/src/calendar/DateField.tsx +0 -200
  19. package/src/calendar/DatePicker.tsx +0 -298
  20. package/src/calendar/RangeCalendar.tsx +0 -236
  21. package/src/calendar/TimeField.tsx +0 -196
  22. package/src/calendar/index.tsx +0 -223
  23. package/src/checkbox/index.tsx +0 -257
  24. package/src/color/index.tsx +0 -687
  25. package/src/combobox/index.tsx +0 -383
  26. package/src/components.css +0 -1077
  27. package/src/custom/calendar-card/index.tsx +0 -66
  28. package/src/custom/chip/index.tsx +0 -46
  29. package/src/custom/conversation/index.tsx +0 -105
  30. package/src/custom/event-card/index.tsx +0 -132
  31. package/src/custom/header/index.tsx +0 -33
  32. package/src/custom/lateral-nav/index.tsx +0 -88
  33. package/src/custom/logo/index.tsx +0 -58
  34. package/src/custom/nav-header/index.tsx +0 -42
  35. package/src/custom/page-layout/index.tsx +0 -29
  36. package/src/custom/profile-card/index.tsx +0 -64
  37. package/src/custom/project-card/index.tsx +0 -59
  38. package/src/custom/timeline-item/index.tsx +0 -105
  39. package/src/dialog/Dialog.tsx +0 -260
  40. package/src/dialog/index.tsx +0 -3
  41. package/src/disclosure/index.tsx +0 -307
  42. package/src/gridlist/index.tsx +0 -403
  43. package/src/icon/icons/GitHubIcon.tsx +0 -20
  44. package/src/icon/index.tsx +0 -48
  45. package/src/index.ts +0 -322
  46. package/src/landmark/index.tsx +0 -231
  47. package/src/link/index.tsx +0 -130
  48. package/src/listbox/index.tsx +0 -231
  49. package/src/menu/index.tsx +0 -297
  50. package/src/meter/index.tsx +0 -163
  51. package/src/numberfield/index.tsx +0 -482
  52. package/src/popover/index.tsx +0 -260
  53. package/src/progress-bar/index.tsx +0 -169
  54. package/src/radio/index.tsx +0 -173
  55. package/src/searchfield/index.tsx +0 -453
  56. package/src/select/index.tsx +0 -349
  57. package/src/separator/index.tsx +0 -141
  58. package/src/slider/index.tsx +0 -382
  59. package/src/styles.css +0 -450
  60. package/src/switch/ToggleSwitch.tsx +0 -112
  61. package/src/switch/index.tsx +0 -90
  62. package/src/table/index.tsx +0 -531
  63. package/src/tabs/index.tsx +0 -273
  64. package/src/tag-group/index.tsx +0 -240
  65. package/src/test-utils/index.ts +0 -32
  66. package/src/textfield/index.tsx +0 -211
  67. package/src/theme.css +0 -101
  68. package/src/toast/index.tsx +0 -324
  69. package/src/toolbar/index.tsx +0 -108
  70. package/src/tooltip/index.tsx +0 -197
  71. package/src/tree/index.tsx +0 -494
@@ -1,207 +0,0 @@
1
- /**
2
- * Breadcrumbs component for proyecto-viviana-ui
3
- *
4
- * Styled breadcrumbs component built on top of solidaria-components.
5
- * Inspired by Spectrum 2's Breadcrumbs component patterns.
6
- */
7
-
8
- import { type JSX, splitProps, createContext, useContext } from 'solid-js'
9
- import {
10
- Breadcrumbs as HeadlessBreadcrumbs,
11
- BreadcrumbItem as HeadlessBreadcrumbItem,
12
- type BreadcrumbsProps as HeadlessBreadcrumbsProps,
13
- type BreadcrumbItemProps as HeadlessBreadcrumbItemProps,
14
- type BreadcrumbsRenderProps,
15
- type BreadcrumbItemRenderProps,
16
- } from '@proyecto-viviana/solidaria-components'
17
-
18
- // ============================================
19
- // SIZE CONTEXT
20
- // ============================================
21
-
22
- export type BreadcrumbsSize = 'sm' | 'md' | 'lg'
23
- export type BreadcrumbsVariant = 'default' | 'subtle'
24
-
25
- interface BreadcrumbsContextValue {
26
- size: BreadcrumbsSize
27
- variant: BreadcrumbsVariant
28
- showSeparator: boolean
29
- }
30
-
31
- const BreadcrumbsSizeContext = createContext<BreadcrumbsContextValue>({
32
- size: 'md',
33
- variant: 'default',
34
- showSeparator: true,
35
- })
36
-
37
- // ============================================
38
- // TYPES
39
- // ============================================
40
-
41
- export interface BreadcrumbsProps<T> extends Omit<HeadlessBreadcrumbsProps<T>, 'class' | 'style'> {
42
- /** The size of the breadcrumbs. */
43
- size?: BreadcrumbsSize
44
- /** The visual variant. */
45
- variant?: BreadcrumbsVariant
46
- /** Whether to show separators between items. */
47
- showSeparator?: boolean
48
- /** Additional CSS class name. */
49
- class?: string
50
- }
51
-
52
- export interface BreadcrumbItemProps extends Omit<HeadlessBreadcrumbItemProps, 'class' | 'style'> {
53
- /** Additional CSS class name. */
54
- class?: string
55
- }
56
-
57
- // ============================================
58
- // STYLES
59
- // ============================================
60
-
61
- const sizeStyles = {
62
- sm: {
63
- text: 'text-sm',
64
- icon: 'h-3 w-3',
65
- gap: 'gap-1',
66
- },
67
- md: {
68
- text: 'text-base',
69
- icon: 'h-4 w-4',
70
- gap: 'gap-1.5',
71
- },
72
- lg: {
73
- text: 'text-lg',
74
- icon: 'h-5 w-5',
75
- gap: 'gap-2',
76
- },
77
- }
78
-
79
- const variantStyles = {
80
- default: {
81
- item: 'text-primary-400 hover:text-primary-200',
82
- current: 'text-primary-100 font-medium',
83
- separator: 'text-primary-500',
84
- },
85
- subtle: {
86
- item: 'text-primary-500 hover:text-primary-300',
87
- current: 'text-primary-200',
88
- separator: 'text-primary-600',
89
- },
90
- }
91
-
92
- // ============================================
93
- // BREADCRUMBS COMPONENT
94
- // ============================================
95
-
96
- /**
97
- * Breadcrumbs show hierarchy and navigational context for a user's location within an application.
98
- *
99
- * Built on solidaria-components Breadcrumbs for full accessibility support.
100
- */
101
- export function Breadcrumbs<T>(props: BreadcrumbsProps<T>): JSX.Element {
102
- const [local, headlessProps] = splitProps(props, [
103
- 'size',
104
- 'variant',
105
- 'showSeparator',
106
- 'class',
107
- ])
108
-
109
- const size = local.size ?? 'md'
110
- const variant = local.variant ?? 'default'
111
- const showSeparator = local.showSeparator ?? true
112
- const customClass = local.class ?? ''
113
-
114
- const getClassName = (renderProps: BreadcrumbsRenderProps): string => {
115
- const base = 'flex items-center'
116
- const sizeClass = sizeStyles[size].gap
117
- const disabledClass = renderProps.isDisabled ? 'opacity-50' : ''
118
- return [base, sizeClass, disabledClass, customClass].filter(Boolean).join(' ')
119
- }
120
-
121
- return (
122
- <BreadcrumbsSizeContext.Provider value={{ size, variant, showSeparator }}>
123
- <HeadlessBreadcrumbs
124
- {...headlessProps}
125
- class={getClassName}
126
- children={props.children}
127
- />
128
- </BreadcrumbsSizeContext.Provider>
129
- )
130
- }
131
-
132
- // ============================================
133
- // BREADCRUMB ITEM COMPONENT
134
- // ============================================
135
-
136
- /**
137
- * A BreadcrumbItem represents an individual breadcrumb in the navigation trail.
138
- */
139
- export function BreadcrumbItem(props: BreadcrumbItemProps): JSX.Element {
140
- const [local, headlessProps] = splitProps(props, ['class'])
141
- const ctx = useContext(BreadcrumbsSizeContext)
142
- const customClass = local.class ?? ''
143
-
144
- const getClassName = (renderProps: BreadcrumbItemRenderProps): string => {
145
- const sizeClass = sizeStyles[ctx.size].text
146
- const vStyles = variantStyles[ctx.variant]
147
-
148
- let stateClass: string
149
- if (renderProps.isCurrent) {
150
- stateClass = vStyles.current
151
- } else if (renderProps.isDisabled) {
152
- stateClass = 'text-primary-600 cursor-not-allowed'
153
- } else {
154
- stateClass = vStyles.item
155
- }
156
-
157
- const cursorClass = renderProps.isCurrent || renderProps.isDisabled ? '' : 'cursor-pointer'
158
- const transitionClass = 'transition-colors duration-150'
159
- const focusClass = renderProps.isFocusVisible
160
- ? 'ring-2 ring-accent-300 ring-offset-1 ring-offset-bg-400 outline-none rounded'
161
- : ''
162
-
163
- return [sizeClass, stateClass, cursorClass, transitionClass, focusClass, customClass].filter(Boolean).join(' ')
164
- }
165
-
166
- const vStyles = variantStyles[ctx.variant]
167
- // Hide separator on first item, and on current (last) item
168
- const separatorClass = `${sizeStyles[ctx.size].icon} ${vStyles.separator} mx-1 shrink-0 hidden data-current:hidden [&:not([data-current])]:block [li:first-child_&]:!hidden`
169
-
170
- // Wrap children with separator icon
171
- const renderChildren = () => (
172
- <>
173
- {/* Separator shows before items except first and current */}
174
- {ctx.showSeparator && <ChevronIcon class={separatorClass} />}
175
- {props.children as JSX.Element}
176
- </>
177
- )
178
-
179
- return (
180
- <HeadlessBreadcrumbItem
181
- {...headlessProps}
182
- class={getClassName}
183
- children={renderChildren()}
184
- />
185
- )
186
- }
187
-
188
- // ============================================
189
- // ICONS
190
- // ============================================
191
-
192
- function ChevronIcon(props: { class?: string }): JSX.Element {
193
- return (
194
- <svg
195
- class={props.class}
196
- fill="none"
197
- viewBox="0 0 24 24"
198
- stroke="currentColor"
199
- stroke-width="2"
200
- >
201
- <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" />
202
- </svg>
203
- )
204
- }
205
-
206
- // Attach sub-components for convenience
207
- Breadcrumbs.Item = BreadcrumbItem
@@ -1,74 +0,0 @@
1
- /**
2
- * Button component for proyecto-viviana-ui
3
- *
4
- * A styled button component built on top of solidaria-components.
5
- * This component only handles styling - all behavior and accessibility
6
- * is provided by the headless Button from solidaria-components.
7
- */
8
-
9
- import { type JSX, splitProps, mergeProps as solidMergeProps } from 'solid-js';
10
- import { Button as HeadlessButton, type ButtonRenderProps } from '@proyecto-viviana/solidaria-components';
11
- import type { ButtonProps } from './types';
12
-
13
- /**
14
- * Buttons allow users to perform an action or to navigate to another page.
15
- * They have multiple styles for various needs, and are ideal for calling attention to
16
- * where a user needs to do something in order to move forward in a flow.
17
- *
18
- * Built on solidaria-components Button for full accessibility support.
19
- * Styles are defined in components.css using the vui-button class system.
20
- */
21
- export function Button(props: ButtonProps): JSX.Element {
22
- const defaultProps: Partial<ButtonProps> = {
23
- variant: 'primary',
24
- buttonStyle: 'fill',
25
- size: 'md',
26
- };
27
-
28
- const merged = solidMergeProps(defaultProps, props);
29
-
30
- const [local, headlessProps] = splitProps(merged, [
31
- 'variant',
32
- 'buttonStyle',
33
- 'size',
34
- 'fullWidth',
35
- 'staticColor',
36
- 'class',
37
- ]);
38
-
39
- // Generate class based on render props
40
- const getClassName = (renderProps: ButtonRenderProps): string => {
41
- const classList = [
42
- 'vui-button',
43
- `vui-button--${local.buttonStyle}`,
44
- `vui-button--${local.variant}`,
45
- `vui-button--${local.size}`,
46
- ];
47
-
48
- if (renderProps.isPressed) {
49
- classList.push('is-pressed');
50
- }
51
-
52
- if (local.fullWidth) {
53
- classList.push('vui-button--full-width');
54
- }
55
-
56
- if (local.class) {
57
- classList.push(local.class);
58
- }
59
-
60
- return classList.join(' ');
61
- };
62
-
63
- return (
64
- <HeadlessButton
65
- {...headlessProps}
66
- class={getClassName}
67
- data-variant={local.variant}
68
- data-style={local.buttonStyle}
69
- data-static-color={local.staticColor || undefined}
70
- >
71
- {props.children}
72
- </HeadlessButton>
73
- );
74
- }
@@ -1,2 +0,0 @@
1
- export { Button } from './Button';
2
- export type { ButtonProps, ButtonVariant, ButtonStyle, ButtonSize, StaticColor } from './types';
@@ -1,24 +0,0 @@
1
- import type { JSX } from 'solid-js';
2
- import type { ButtonProps as HeadlessButtonProps } from '@proyecto-viviana/solidaria-components';
3
-
4
- export type ButtonVariant = 'primary' | 'secondary' | 'accent' | 'positive' | 'negative' | 'ghost' | 'link';
5
- export type ButtonStyle = 'fill' | 'outline';
6
- export type ButtonSize = 'sm' | 'md' | 'lg';
7
- export type StaticColor = 'white' | 'black';
8
-
9
- export interface ButtonProps extends Omit<HeadlessButtonProps, 'class' | 'children' | 'style'> {
10
- /** The content to display in the button. */
11
- children?: JSX.Element;
12
- /** The visual style of the button. */
13
- variant?: ButtonVariant;
14
- /** The background style of the button. */
15
- buttonStyle?: ButtonStyle;
16
- /** The size of the button. */
17
- size?: ButtonSize;
18
- /** Whether the button should take up the full width of its container. */
19
- fullWidth?: boolean;
20
- /** The static color style to apply. Useful when the button appears over a color background. */
21
- staticColor?: StaticColor;
22
- /** Additional CSS class name. */
23
- class?: string;
24
- }
@@ -1,200 +0,0 @@
1
- /**
2
- * DateField component for proyecto-viviana-ui
3
- *
4
- * Styled date field component with segment-based editing.
5
- */
6
-
7
- import { type JSX, splitProps } from 'solid-js';
8
- import {
9
- DateField as HeadlessDateField,
10
- DateInput,
11
- DateSegment,
12
- type DateFieldProps as HeadlessDateFieldProps,
13
- type CalendarDate,
14
- type DateValue,
15
- } from '@proyecto-viviana/solidaria-components';
16
-
17
- // ============================================
18
- // TYPES
19
- // ============================================
20
-
21
- export type DateFieldSize = 'sm' | 'md' | 'lg';
22
-
23
- export interface DateFieldProps<T extends DateValue = DateValue>
24
- extends Omit<HeadlessDateFieldProps<T>, 'class' | 'style' | 'children'> {
25
- /** The size of the field. @default 'md' */
26
- size?: DateFieldSize;
27
- /** Additional CSS class name. */
28
- class?: string;
29
- /** Label for the field. */
30
- label?: string;
31
- /** Description text. */
32
- description?: string;
33
- /** Error message. */
34
- errorMessage?: string;
35
- }
36
-
37
- // ============================================
38
- // STYLES
39
- // ============================================
40
-
41
- const sizeStyles = {
42
- sm: {
43
- container: 'text-sm',
44
- input: 'px-2 py-1 gap-0.5',
45
- segment: 'px-0.5',
46
- label: 'text-xs',
47
- },
48
- md: {
49
- container: 'text-base',
50
- input: 'px-3 py-2 gap-1',
51
- segment: 'px-1',
52
- label: 'text-sm',
53
- },
54
- lg: {
55
- container: 'text-lg',
56
- input: 'px-4 py-3 gap-1.5',
57
- segment: 'px-1.5',
58
- label: 'text-base',
59
- },
60
- };
61
-
62
- // ============================================
63
- // DATE FIELD COMPONENT
64
- // ============================================
65
-
66
- /**
67
- * A date field allows users to enter and edit date values using a keyboard.
68
- *
69
- * @example
70
- * ```tsx
71
- * // Basic usage
72
- * <DateField label="Birth date" />
73
- *
74
- * // Controlled
75
- * const [date, setDate] = createSignal<CalendarDate | null>(null);
76
- * <DateField
77
- * label="Event date"
78
- * value={date()}
79
- * onChange={setDate}
80
- * />
81
- *
82
- * // With validation
83
- * <DateField
84
- * label="Future date"
85
- * minValue={today(getLocalTimeZone())}
86
- * errorMessage="Date must be in the future"
87
- * />
88
- * ```
89
- */
90
- export function DateField<T extends DateValue = CalendarDate>(
91
- props: DateFieldProps<T>
92
- ): JSX.Element {
93
- const [local, rest] = splitProps(props, [
94
- 'size',
95
- 'class',
96
- 'label',
97
- 'description',
98
- 'errorMessage',
99
- 'isInvalid',
100
- ]);
101
-
102
- const size = () => local.size ?? 'md';
103
- const sizeConfig = () => sizeStyles[size()];
104
- const isInvalid = () => local.isInvalid || !!local.errorMessage;
105
-
106
- return (
107
- <HeadlessDateField
108
- {...rest}
109
- isInvalid={isInvalid()}
110
- class={`
111
- flex flex-col gap-1
112
- ${sizeConfig().container}
113
- ${local.class ?? ''}
114
- `}
115
- >
116
- {/* Label */}
117
- {local.label && (
118
- <label class={`font-medium text-primary-200 ${sizeConfig().label}`}>
119
- {local.label}
120
- {rest.isRequired && <span class="text-red-500 ml-0.5">*</span>}
121
- </label>
122
- )}
123
-
124
- {/* Input container */}
125
- <DateInput
126
- class={({ isFocused, isDisabled }) => {
127
- const base = `
128
- inline-flex items-center
129
- ${sizeConfig().input}
130
- bg-bg-400 rounded-md border
131
- transition-colors duration-150
132
- `;
133
-
134
- let borderClass = 'border-primary-600';
135
- if (isInvalid()) {
136
- borderClass = 'border-red-500';
137
- } else if (isFocused) {
138
- borderClass = 'border-accent';
139
- }
140
-
141
- const disabledClass = isDisabled
142
- ? 'opacity-50 cursor-not-allowed'
143
- : '';
144
-
145
- const focusClass = isFocused
146
- ? 'ring-2 ring-accent/30'
147
- : '';
148
-
149
- return `${base} ${borderClass} ${disabledClass} ${focusClass}`.trim();
150
- }}
151
- >
152
- {(segment) => (
153
- <DateSegment
154
- segment={segment}
155
- class={({ isFocused, isPlaceholder, isEditable }) => {
156
- const base = `
157
- ${sizeConfig().segment}
158
- rounded
159
- outline-none
160
- tabular-nums
161
- `;
162
-
163
- let stateClass = '';
164
- if (segment.type === 'literal') {
165
- stateClass = 'text-primary-400';
166
- } else if (isPlaceholder) {
167
- stateClass = 'text-primary-500 italic';
168
- } else {
169
- stateClass = 'text-primary-100';
170
- }
171
-
172
- const focusClass = isFocused && isEditable
173
- ? 'bg-accent text-white'
174
- : '';
175
-
176
- return `${base} ${stateClass} ${focusClass}`.trim();
177
- }}
178
- />
179
- )}
180
- </DateInput>
181
-
182
- {/* Description */}
183
- {local.description && !isInvalid() && (
184
- <p class={`text-primary-400 ${sizeConfig().label}`}>
185
- {local.description}
186
- </p>
187
- )}
188
-
189
- {/* Error message */}
190
- {isInvalid() && local.errorMessage && (
191
- <p class={`text-red-500 ${sizeConfig().label}`}>
192
- {local.errorMessage}
193
- </p>
194
- )}
195
- </HeadlessDateField>
196
- );
197
- }
198
-
199
- // Re-export types
200
- export type { CalendarDate, DateValue };