@juligc99/loro-ui 0.0.17 → 0.0.19

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
@@ -1,164 +1,101 @@
1
1
  # Loro UI
2
2
 
3
- Loro UI is the Angular design system for Al Loro. It contains standalone Angular components, design tokens, icons, images, Storybook documentation and npm publishing configuration.
3
+ Loro UI is the Angular 21 design system for Al Loro. It ships standalone components, theme tokens, icons, images, and Storybook docs.
4
4
 
5
- ## Requirements
6
-
7
- - Node `20.19+`, `22.12+` or `24+`
8
- - npm `10.9+`
9
- - Angular `21+`
10
-
11
- Node 22 LTS is recommended for local Storybook work.
12
-
13
- ## Install dependencies
5
+ ## Use in an app
14
6
 
15
7
  ```bash
16
- npm install
17
- ```
18
-
19
- ## Development
20
-
21
- ```bash
22
- npm run build:loro-ui
23
- npm run storybook
8
+ npm i @juligc99/loro-ui
24
9
  ```
25
10
 
26
- Stable Storybook run with cache cleanup:
11
+ ```scss
12
+ @use 'sass:meta';
27
13
 
28
- ```bash
29
- npm run storybook:stable
14
+ @include meta.load-css('@juligc99/loro-ui/design-tokens/loro-theme.scss');
30
15
  ```
31
16
 
32
- Build static Storybook:
33
-
34
- ```bash
35
- npm run build-storybook:stable
17
+ ```ts
18
+ import { LoroButton, LoroInput } from '@juligc99/loro-ui';
36
19
  ```
37
20
 
38
- ## Package structure
39
-
40
- ```txt
41
- projects/loro-ui/
42
- ├── .storybook/
43
- ├── scripts/
44
- ├── src/
45
- │ ├── lib/assets/
46
- │ ├── lib/components/
47
- │ ├── lib/design-tokens/
48
- │ ├── lib/docs/
49
- │ ├── lib/services/
50
- │ ├── lib/styles/
51
- │ ├── public-api.ts
52
- │ └── styles.scss
53
- ├── ng-package.json
54
- ├── package.json
55
- └── tsconfig.storybook.json
21
+ ```ts
22
+ @Component({
23
+ standalone: true,
24
+ imports: [LoroButton, LoroInput],
25
+ template: `
26
+ <loro-button label="Guardar" />
27
+ <loro-input label="Email" type="email" />
28
+ `,
29
+ })
30
+ export class ExampleComponent {}
56
31
  ```
57
32
 
58
- ## Angular best practices used
59
-
60
- - Standalone components.
61
- - Signal inputs/models.
62
- - `ChangeDetectionStrategy.OnPush`.
63
- - `@angular/forms/signals` support for reusable form controls.
64
- - Public API through `projects/loro-ui/src/public-api.ts`.
65
- - Relative internal imports to avoid broken npm bundles.
66
- - Sass tokens exported as package assets.
67
-
68
- ## Sass API
33
+ ## Forms contract
69
34
 
70
- Use breakpoints from the package:
35
+ Form components in Loro UI are built primarily for `@angular/forms/signals`.
36
+ They follow the `FormValueControl<T>` / `FormCheckboxControl` contracts and the
37
+ `model()`-based value pattern used across the design system.
71
38
 
72
- ```scss
73
- @use '@juligc99/loro-ui/styles/breakpoints' as bp;
74
- ```
39
+ If your app still uses classic Angular `FormGroup` / `formControlName`, you will
40
+ need a `ControlValueAccessor` bridge or adapter layer. The signals-based contract
41
+ is the supported baseline for these components.
75
42
 
76
- Use theme tokens globally in an app:
43
+ ## Local development
77
44
 
78
- ```scss
79
- @use 'sass:meta';
80
-
81
- @include meta.load-css('@juligc99/loro-ui/design-tokens/loro-theme.scss');
45
+ ```bash
46
+ npm install
47
+ npm run build
48
+ npm run storybook
82
49
  ```
83
50
 
84
- Copy package assets in the consuming Angular app if you use images/fonts/icons by path:
51
+ Use `npm run storybook` to check components and docs in the browser.
85
52
 
86
- ```json
87
- {
88
- "glob": "**/*",
89
- "input": "node_modules/@juligc99/loro-ui/assets/loro-ui",
90
- "output": "/assets/loro-ui"
91
- }
92
- ```
53
+ ## Storybook remoto with ngrok
93
54
 
94
- ## Publish to npm
55
+ Use ngrok when you want to test the local Storybook from other devices without deploying.
95
56
 
96
- The workspace root is private and must not be published. The publishable package is generated in `dist/loro-ui`.
57
+ Install ngrok:
97
58
 
98
59
  ```bash
99
- npm login
100
- npm run publish:loro-ui:dry
101
- npm run publish:loro-ui
60
+ brew install ngrok/ngrok/ngrok
102
61
  ```
103
62
 
104
- Manual flow:
63
+ Add the auth token:
105
64
 
106
65
  ```bash
107
- npm run build:loro-ui
108
- cd dist/loro-ui
109
- npm publish --dry-run
110
- npm publish --access public
66
+ ngrok config add-authtoken 3G7ncpInz0dIbGwE1sLObjhbRA9_3Uo869KrBLkHuHXcxyK35
111
67
  ```
112
68
 
113
- ## Versioning
69
+ Start Storybook and expose it publicly:
114
70
 
115
71
  ```bash
116
- npm run version:loro-ui:patch
117
- npm run publish:loro-ui
72
+ npm run storybook
73
+ ngrok http 6006 --host-header=localhost:6006
118
74
  ```
119
75
 
120
- The current package version is `0.0.11`.
76
+ Then open the ngrok URL on any phone, tablet, or another computer on the same network to test the UI in a real device.
121
77
 
122
- ## Consume from an Angular app
78
+ ## Local package test
123
79
 
124
80
  ```bash
125
- npm i @juligc99/loro-ui
81
+ npm run build
82
+ cd dist/loro-ui
83
+ npm pack
126
84
  ```
127
85
 
128
- ```ts
129
- import { LoroButton, LoroInput } from '@juligc99/loro-ui';
130
- ```
86
+ Then install the generated tarball in the consuming app.
131
87
 
132
- ```ts
133
- @Component({
134
- standalone: true,
135
- imports: [LoroButton, LoroInput],
136
- template: `
137
- <loro-button label="Guardar" />
138
- <loro-input label="Email" type="email" />
139
- `,
140
- })
141
- export class ExampleComponent {}
142
- ```
143
-
144
- ## Quality checks
88
+ ## Publish
145
89
 
146
90
  ```bash
147
- npm run lint:all
148
- npm run verify
91
+ npm run build
92
+ cd dist/loro-ui
93
+ npm publish --access public
149
94
  ```
150
95
 
96
+ ## Package API
151
97
 
152
- ## Form controls
153
-
154
- Form components that represent values implement Angular Signal Forms control contracts:
155
-
156
- - `LoroInput`, `LoroAuthField`, `LoroTextArea`, `LoroDropdown`, `LoroSegmentedControl`: `FormValueControl<string>`.
157
- - `LoroCheckbox`, `LoroToggle`: `FormCheckboxControl`.
158
-
159
- Use them from an app with `FormField` from `@angular/forms/signals`:
160
-
161
- ```html
162
- <loro-input [formField]="form.email" label="Email" type="email" />
163
- <loro-checkbox [formField]="form.acceptTerms">Acepto los términos</loro-checkbox>
164
- ```
98
+ - Components are standalone.
99
+ - The public entrypoint is `projects/loro-ui/src/public-api.ts`.
100
+ - Sass helpers are exposed through package subpaths.
101
+ - Assets are copied from `assets/loro-ui` in the package output.
@@ -0,0 +1,3 @@
1
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="m6.7 5.29 5.3 5.3 5.3-5.3a1 1 0 0 1 1.41 1.41L13.41 12l5.3 5.3a1 1 0 1 1-1.41 1.41L12 13.41l-5.3 5.3a1 1 0 1 1-1.41-1.41l5.3-5.3-5.3-5.3A1 1 0 1 1 6.7 5.29Z"/>
3
+ </svg>
@@ -424,6 +424,12 @@ export const LORO_ICON_ASSETS = [
424
424
  "path": "assets/loro-ui/icons/warning.svg",
425
425
  "layer": "Status",
426
426
  "fileName": "warning.svg"
427
+ },
428
+ {
429
+ "name": "icon-x",
430
+ "path": "assets/loro-ui/icons/x.svg",
431
+ "layer": "Product",
432
+ "fileName": "x.svg"
427
433
  }
428
434
  ] as const satisfies readonly LoroIconAsset[];
429
435
 
@@ -493,7 +499,8 @@ export const LORO_ICON_PATHS = {
493
499
  "icon-trash": "assets/loro-ui/icons/trash.svg",
494
500
  "icon-trend": "assets/loro-ui/icons/trend.svg",
495
501
  "icon-user": "assets/loro-ui/icons/user.svg",
496
- "icon-warning": "assets/loro-ui/icons/warning.svg"
502
+ "icon-warning": "assets/loro-ui/icons/warning.svg",
503
+ "icon-x": "assets/loro-ui/icons/x.svg"
497
504
  } as const;
498
505
 
499
506
  export const LORO_ICON_LEGACY_NAMES = {
@@ -562,7 +569,8 @@ export const LORO_ICON_LEGACY_NAMES = {
562
569
  "trash": "icon-trash",
563
570
  "trend": "icon-trend",
564
571
  "user": "icon-user",
565
- "warning": "icon-warning"
572
+ "warning": "icon-warning",
573
+ "x": "icon-x"
566
574
  } as const;
567
575
 
568
576
  export type LoroIconAssetName = keyof typeof LORO_ICON_PATHS;
@@ -1,15 +1,18 @@
1
1
  :root {
2
2
  color-scheme: light;
3
3
 
4
+ /* Typography */
4
5
  --loro-font-brand: 'Manrope', 'Inter', system-ui, sans-serif;
5
6
  --loro-font-fallback: 'Inter', system-ui, sans-serif;
6
7
 
8
+ /* Brand palette */
7
9
  --loro-primary-900: #2e176a;
8
10
  --loro-primary-700: #5b33d6;
9
11
  --loro-primary-500: #6c3cff;
10
12
  --loro-primary-200: #ede9fe;
11
13
  --loro-accent-yellow: #ffb703;
12
14
 
15
+ /* Core surfaces and text */
13
16
  --loro-background: #f6f4fb;
14
17
  --loro-surface: #ffffff;
15
18
  --loro-surface-soft: rgba(255, 255, 255, 0.78);
@@ -29,26 +32,30 @@
29
32
  --loro-border-contrast: rgba(255, 255, 255, 0.22);
30
33
  --loro-focus-ring: rgba(108, 60, 255, 0.26);
31
34
 
32
- --loro-disabled-surface: #ebe7f5;
33
- --loro-disabled-border: rgba(43, 35, 80, 0.18);
34
- --loro-disabled-text: #6f668b;
35
- --loro-disabled-primary-surface: linear-gradient(135deg, #a995db, #8d77c8);
36
- --loro-disabled-primary-text: rgba(255, 255, 255, 0.72);
37
- --loro-social-disabled-surface: #eef0f5;
38
- --loro-social-disabled-border: rgba(43, 35, 80, 0.18);
39
- --loro-social-disabled-text: #5d6475;
40
- --loro-social-disabled-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.64);
35
+ /* Disabled states */
36
+ --loro-disabled-surface: #c6c2d4;
37
+ --loro-disabled-border: rgba(43, 35, 80, 0.1);
38
+ --loro-disabled-text: rgba(255, 255, 255, 0.94);
39
+ --loro-disabled-primary-surface: #b3acc7;
40
+ --loro-disabled-primary-text: rgba(255, 255, 255, 0.94);
41
+ --loro-social-disabled-surface: #d4d0df;
42
+ --loro-social-disabled-border: rgba(43, 35, 80, 0.08);
43
+ --loro-social-disabled-text: rgba(255, 255, 255, 0.94);
44
+ --loro-social-disabled-shadow: none;
41
45
 
42
- --loro-shadow-soft: 0 10px 30px rgba(34, 25, 73, 0.07);
43
- --loro-shadow-panel: 0 24px 60px rgba(40, 26, 92, 0.12);
44
- --loro-shadow-button: 0 12px 24px rgba(91, 51, 214, 0.18);
46
+ /* Elevation */
47
+ --loro-shadow-soft: 0 8px 24px rgba(34, 25, 73, 0.06);
48
+ --loro-shadow-panel: 0 20px 48px rgba(40, 26, 92, 0.1);
49
+ --loro-shadow-button: 0 8px 20px rgba(91, 51, 214, 0.12);
45
50
  --loro-shadow-brand: 0 18px 44px rgba(46, 23, 106, 0.22), 0 2px 10px rgba(31, 10, 102, 0.1);
46
51
 
52
+ /* Radius */
47
53
  --loro-radius-card: 1.5rem;
48
54
  --loro-radius-card-lg: 2rem;
49
55
  --loro-radius-input: 1rem;
50
56
  --loro-radius-pill: 999px;
51
57
 
58
+ /* Spacing */
52
59
  --loro-space-1: 0.25rem;
53
60
  --loro-space-2: 0.5rem;
54
61
  --loro-space-3: 0.75rem;
@@ -57,6 +64,7 @@
57
64
  --loro-space-6: 2rem;
58
65
  --loro-space-7: 3rem;
59
66
 
67
+ /* Brand gradients and accent surfaces */
60
68
  --loro-brand-start: #5b33d6;
61
69
  --loro-brand-end: #2e176a;
62
70
  --loro-brand-soft-start: #6c3cff;
@@ -70,6 +78,7 @@
70
78
  --loro-danger-surface: #fff0f1;
71
79
  --loro-danger-text: #b0223b;
72
80
 
81
+ /* Page and shell */
73
82
  --loro-page-background:
74
83
  radial-gradient(circle at 14% 12%, rgba(108, 60, 255, 0.1), transparent 24%),
75
84
  radial-gradient(circle at 86% 18%, rgba(91, 51, 214, 0.06), transparent 22%),
@@ -80,6 +89,7 @@
80
89
  --loro-shell-border: rgba(255, 255, 255, 0.56);
81
90
  --loro-shell-shadow: 0 24px 60px rgba(40, 26, 92, 0.12);
82
91
 
92
+ /* Navigation */
83
93
  --loro-nav-desktop-width: 16rem;
84
94
  --loro-nav-mobile-max-width: 30rem;
85
95
  --loro-nav-desktop-offset: 1.5rem;
@@ -152,9 +162,8 @@
152
162
  inset 0 0 0 1px rgba(176, 34, 59, 0.04),
153
163
  0 8px 18px rgba(176, 34, 59, 0.08);
154
164
 
165
+ /* Header and layout */
155
166
  --loro-header-desktop-min-height: 2.5rem;
156
-
157
- /* Layout shell tokens */
158
167
  --loro-layout-mobile-gutter: clamp(1rem, 4vw, 1.5rem);
159
168
  --loro-layout-mobile-header-bar-height: 3.45rem;
160
169
  --loro-layout-mobile-header-height: calc(
@@ -172,6 +181,7 @@
172
181
  --loro-layout-desktop-header-height: max(3rem, var(--loro-header-desktop-min-height, 0.5rem));
173
182
  --loro-layout-notification-popover-width: min(26rem, calc(100vw - var(--loro-layout-desktop-nav-width) - 4rem));
174
183
 
184
+ /* Cards and home surfaces */
175
185
  --loro-dashboard-card-media-size: 5rem;
176
186
  --loro-dashboard-card-content-min-height: 5.25rem;
177
187
  --loro-dashboard-card-title-min-height: 1.375rem;
@@ -212,6 +222,7 @@
212
222
  --loro-home-card-glow: radial-gradient(circle at 86% 14%, rgba(210, 193, 255, 0.16) 0%, transparent 34%);
213
223
  --loro-home-card-sheen: none;
214
224
 
225
+ /* Legacy aliases kept for compatibility */
215
226
  --color-primary: var(--loro-primary-500);
216
227
  --color-primary-dark: var(--loro-primary-900);
217
228
  --color-secondary: var(--loro-primary-700);
@@ -222,6 +233,7 @@
222
233
  html[data-theme='dark'] {
223
234
  color-scheme: dark;
224
235
 
236
+ /* Brand palette */
225
237
  --loro-primary-900: #d8c2ff;
226
238
  --loro-primary-700: #b58cff;
227
239
  --loro-primary-500: #9763f1;
@@ -245,21 +257,23 @@ html[data-theme='dark'] {
245
257
  --loro-border-contrast: rgba(255, 255, 255, 0.12);
246
258
  --loro-focus-ring: rgba(181, 140, 255, 0.34);
247
259
 
248
- --loro-disabled-surface: #252a33;
249
- --loro-disabled-border: rgba(255, 255, 255, 0.17);
250
- --loro-disabled-text: #b9c1cb;
251
- --loro-disabled-primary-surface: linear-gradient(135deg, #6f568f, #5b477a);
252
- --loro-disabled-primary-text: rgba(255, 255, 255, 0.68);
253
- --loro-social-disabled-surface: #20252d;
254
- --loro-social-disabled-border: rgba(255, 255, 255, 0.18);
255
- --loro-social-disabled-text: #c0c6cf;
256
- --loro-social-disabled-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04);
260
+ --loro-disabled-surface: #545d6e;
261
+ --loro-disabled-border: rgba(255, 255, 255, 0.1);
262
+ --loro-disabled-text: rgba(255, 255, 255, 0.94);
263
+ --loro-disabled-primary-surface: #5d6678;
264
+ --loro-disabled-primary-text: rgba(255, 255, 255, 0.94);
265
+ --loro-social-disabled-surface: #505a6a;
266
+ --loro-social-disabled-border: rgba(255, 255, 255, 0.08);
267
+ --loro-social-disabled-text: rgba(255, 255, 255, 0.94);
268
+ --loro-social-disabled-shadow: none;
257
269
 
258
- --loro-shadow-soft: 0 14px 36px rgba(0, 0, 0, 0.28);
259
- --loro-shadow-panel: 0 26px 72px rgba(0, 0, 0, 0.34);
260
- --loro-shadow-button: 0 14px 28px rgba(0, 0, 0, 0.32);
270
+ /* Elevation */
271
+ --loro-shadow-soft: 0 12px 28px rgba(0, 0, 0, 0.2);
272
+ --loro-shadow-panel: 0 22px 52px rgba(0, 0, 0, 0.28);
273
+ --loro-shadow-button: 0 8px 18px rgba(0, 0, 0, 0.18);
261
274
  --loro-shadow-brand: 0 18px 48px rgba(4, 3, 15, 0.38), 0 2px 10px rgba(3, 2, 10, 0.22);
262
275
 
276
+ /* Brand gradients and accent surfaces */
263
277
  --loro-brand-start: #b58cff;
264
278
  --loro-brand-end: #7b4cff;
265
279
  --loro-brand-soft-start: #d8c2ff;
@@ -273,6 +287,7 @@ html[data-theme='dark'] {
273
287
  --loro-danger-surface: rgba(248, 113, 113, 0.14);
274
288
  --loro-danger-text: #fca5a5;
275
289
 
290
+ /* Page and shell */
276
291
  --loro-page-background:
277
292
  radial-gradient(circle at 18% 14%, rgba(181, 140, 255, 0.08), transparent 22%),
278
293
  radial-gradient(circle at 84% 16%, rgba(151, 99, 241, 0.06), transparent 20%),
@@ -283,7 +298,7 @@ html[data-theme='dark'] {
283
298
  --loro-shell-border: rgba(255, 255, 255, 0.1);
284
299
  --loro-shell-shadow: 0 24px 72px rgba(0, 0, 0, 0.34);
285
300
 
286
- /* Layout shell tokens */
301
+ /* Navigation */
287
302
  --loro-layout-notification-popover-width: min(26rem, calc(100vw - var(--loro-layout-desktop-nav-width) - 4rem));
288
303
 
289
304
  --loro-nav-surface-background: #1b1f27;
@@ -347,6 +362,8 @@ html[data-theme='dark'] {
347
362
  --loro-nav-button-danger-hover-shadow:
348
363
  inset 0 0 0 1px rgba(252, 165, 165, 0.06),
349
364
  0 12px 24px rgba(0, 0, 0, 0.18);
365
+
366
+ /* Cards and home surfaces */
350
367
  --loro-home-hero-border: rgba(255, 255, 255, 0.08);
351
368
  --loro-home-hero-bg:
352
369
  radial-gradient(circle at 100% 0%, rgba(191, 150, 255, 0.14) 0%, transparent 34%),
@@ -379,6 +396,7 @@ html[data-theme='dark'] {
379
396
  --loro-home-card-glow: radial-gradient(circle at 86% 14%, rgba(197, 166, 255, 0.14) 0%, transparent 34%);
380
397
  --loro-home-card-sheen: none;
381
398
 
399
+ /* Legacy aliases kept for compatibility */
382
400
  --color-secondary-dark: #7b4cff;
383
401
  --color-card-bg: rgba(181, 140, 255, 0.1);
384
402
  }