@besaitech/ng-design-system 0.0.11 → 0.0.16

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
@@ -24,12 +24,7 @@ phone input, plus the app shell (top bar + sidebar).
24
24
  npm install @besaitech/ng-design-system
25
25
  ```
26
26
 
27
- Published to the public npm registry, so no `.npmrc` and no read token are needed.
28
-
29
- > Earlier releases were served from an internal GitLab Package Registry and this section carried the
30
- > `@besaitech:registry=…` + `_authToken=…` lines for it. Those instructions no longer match where the
31
- > package comes from — following them against a public install yields a 401 for a registry you do not
32
- > need to reach.
27
+ Public npm registry — no `.npmrc`, no scope mapping and no read token required.
33
28
 
34
29
  ## 2. Tailwind setup
35
30
 
@@ -67,14 +62,17 @@ This is the step that makes the components look right. Tailwind v4 is CSS-first
67
62
  Path is relative to THIS file (src/styles.css → ../node_modules). */
68
63
  @source "../node_modules/@besaitech/ng-design-system";
69
64
 
70
- /* Brand ramp: pick a theme preset. Must come AFTER the tailwindcss import —
71
- Tailwind v4 processes @theme in imported files and later declarations win. */
65
+ /* Tokens. BOTH imports are required, and both must come AFTER the tailwindcss import —
66
+ Tailwind v4 processes @theme in imported files and later declarations win.
67
+ base.css = surfaces, ink, accents, status, radius, layout vars (15 tokens).
68
+ The brand preset = the 11 --color-brand-* steps, and nothing else. */
69
+ @import "@besaitech/ng-design-system/themes/base.css";
72
70
  @import "@besaitech/ng-design-system/themes/saitech.css"; /* blues */
73
71
  /* @import "@besaitech/ng-design-system/themes/belvigo.css"; black */
74
72
 
75
- /* Everything else is yours to tune (Tailwind utilities + CSS vars). */
73
+ /* Override any base default in your own @theme afterwards, e.g. the typeface. */
76
74
  @theme {
77
- /* Neutrals / surfaces */
75
+ /* Neutrals / surfaces (already provided by base.css — shown for reference) */
78
76
  --color-canvas: #f5f6f8;
79
77
  --color-surface: #ffffff;
80
78
  --color-muted: #f8f9fb;
@@ -207,7 +205,6 @@ Import names are the `Sl…` classes; the markup selectors are `sds-…`.
207
205
 
208
206
  | Symptom | Cause / fix |
209
207
  | --- | --- |
210
- | `404 Project not found` on install | `.npmrc` missing the `@besaitech:registry` line, or token lacks access to project 922 |
211
208
  | `403 insufficient_scope` | Token is missing `read_package_registry` scope |
212
209
  | Components render unstyled | Missing/incorrect `@source` line, or no theme preset imported (step 3b) |
213
210
  | Brand colours are wrong / absent | The theme preset is imported BEFORE `@import "tailwindcss"`, so it is overridden |
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, signal, forwardRef, viewChild, numberAttribute, afterRenderEffect, ElementRef, model, output, Injector, afterNextRender, Injectable, TemplateRef, Directive, contentChildren, contentChild } from '@angular/core';
2
+ import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, output, signal, forwardRef, viewChild, numberAttribute, afterRenderEffect, ElementRef, model, Injector, afterNextRender, Injectable, TemplateRef, Directive, contentChildren, contentChild } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule } from '@angular/forms';
@@ -59,6 +59,9 @@ const SDS_ICONS = {
59
59
  filter: '<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>',
60
60
  table: '<path d="M12 3v18"/><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M3 9h18"/><path d="M3 15h18"/>',
61
61
  eye: '<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>',
62
+ // Pairs with `eye` for password reveal. Without it a show/hide toggle has no second state to draw,
63
+ // and aria-pressed alone leaves sighted users with no visible change.
64
+ 'eye-off': '<path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><path d="m2 2 20 20"/><path d="M14.12 14.12a3 3 0 1 1-4.24-4.24"/>',
62
65
  user: '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',
63
66
  'check-circle': '<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',
64
67
  'arrows-clockwise': '<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M3 21v-5h5"/>',
@@ -264,6 +267,21 @@ class SdsInput {
264
267
  clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
265
268
  leadingIcon = input(null, ...(ngDevMode ? [{ debugName: "leadingIcon" }] : []));
266
269
  trailingIcon = input(null, ...(ngDevMode ? [{ debugName: "trailingIcon" }] : []));
270
+ /**
271
+ * A CLICKABLE trailing icon, for the affordances that belong to the field itself — password reveal
272
+ * above all. Distinct from {@link trailingIcon}, which is decorative and explicitly
273
+ * `pointer-events-none`; a consumer who needed a working control previously had to abandon
274
+ * `sds-input` and rebuild the whole field, losing the label/error/aria wiring with it.
275
+ *
276
+ * Always pair it with {@link trailingActionLabel} — an icon-only button with no accessible name is
277
+ * unusable by a screen reader. For a toggle, also bind {@link trailingActionPressed}.
278
+ */
279
+ trailingAction = input(null, ...(ngDevMode ? [{ debugName: "trailingAction" }] : []));
280
+ /** Accessible name for {@link trailingAction}. Translate it in the consuming app. */
281
+ trailingActionLabel = input('', ...(ngDevMode ? [{ debugName: "trailingActionLabel" }] : []));
282
+ /** `aria-pressed` for a toggling action (e.g. show/hide password). Null renders no attribute. */
283
+ trailingActionPressed = input(null, ...(ngDevMode ? [{ debugName: "trailingActionPressed" }] : []));
284
+ trailingActionClick = output();
267
285
  /** Current value (driven by CVA + user input). */
268
286
  value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : []));
269
287
  cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
@@ -278,7 +296,7 @@ class SdsInput {
278
296
  }, ...(ngDevMode ? [{ debugName: "describedBy" }] : []));
279
297
  fieldPadding = computed(() => {
280
298
  const left = this.leadingIcon() ? 'pl-10' : 'pl-3.5';
281
- const right = this.trailingIcon() || this.clearable() ? 'pr-10' : 'pr-3.5';
299
+ const right = this.trailingIcon() || this.clearable() || this.trailingAction() ? 'pr-10' : 'pr-3.5';
282
300
  return `${left} ${right}`;
283
301
  }, ...(ngDevMode ? [{ debugName: "fieldPadding" }] : []));
284
302
  wrapperClasses = computed(() => {
@@ -325,7 +343,7 @@ class SdsInput {
325
343
  this.onTouched();
326
344
  }
327
345
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
328
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsInput, isStandalone: true, selector: "sds-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: true, isRequired: false, transformFunction: null }, trailingIcon: { classPropertyName: "trailingIcon", publicName: "trailingIcon", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
346
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsInput, isStandalone: true, selector: "sds-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: true, isRequired: false, transformFunction: null }, trailingIcon: { classPropertyName: "trailingIcon", publicName: "trailingIcon", isSignal: true, isRequired: false, transformFunction: null }, trailingAction: { classPropertyName: "trailingAction", publicName: "trailingAction", isSignal: true, isRequired: false, transformFunction: null }, trailingActionLabel: { classPropertyName: "trailingActionLabel", publicName: "trailingActionLabel", isSignal: true, isRequired: false, transformFunction: null }, trailingActionPressed: { classPropertyName: "trailingActionPressed", publicName: "trailingActionPressed", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { trailingActionClick: "trailingActionClick" }, host: { classAttribute: "block" }, providers: [
329
347
  {
330
348
  provide: NG_VALUE_ACCESSOR,
331
349
  useExisting: forwardRef(() => SdsInput),
@@ -379,6 +397,18 @@ class SdsInput {
379
397
  >
380
398
  <sds-icon name="x" [size]="15" />
381
399
  </button>
400
+ } @else if (trailingAction()) {
401
+ <button
402
+ type="button"
403
+ [attr.aria-label]="trailingActionLabel() || null"
404
+ [attr.aria-pressed]="trailingActionPressed()"
405
+ [attr.aria-controls]="inputId"
406
+ class="absolute right-2.5 inline-flex h-7 w-7 items-center justify-center rounded-full
407
+ opacity-70 hover:opacity-100 hover:bg-black/5"
408
+ (click)="trailingActionClick.emit()"
409
+ >
410
+ <sds-icon [name]="trailingAction()!" [size]="18" />
411
+ </button>
382
412
  } @else if (trailingIcon()) {
383
413
  <sds-icon
384
414
  [name]="trailingIcon()!"
@@ -465,6 +495,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
465
495
  >
466
496
  <sds-icon name="x" [size]="15" />
467
497
  </button>
498
+ } @else if (trailingAction()) {
499
+ <button
500
+ type="button"
501
+ [attr.aria-label]="trailingActionLabel() || null"
502
+ [attr.aria-pressed]="trailingActionPressed()"
503
+ [attr.aria-controls]="inputId"
504
+ class="absolute right-2.5 inline-flex h-7 w-7 items-center justify-center rounded-full
505
+ opacity-70 hover:opacity-100 hover:bg-black/5"
506
+ (click)="trailingActionClick.emit()"
507
+ >
508
+ <sds-icon [name]="trailingAction()!" [size]="18" />
509
+ </button>
468
510
  } @else if (trailingIcon()) {
469
511
  <sds-icon
470
512
  [name]="trailingIcon()!"
@@ -489,7 +531,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
489
531
  }
490
532
  `,
491
533
  }]
492
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], trailingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingIcon", required: false }] }] } });
534
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], trailingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingIcon", required: false }] }], trailingAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingAction", required: false }] }], trailingActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionLabel", required: false }] }], trailingActionPressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionPressed", required: false }] }], trailingActionClick: [{ type: i0.Output, args: ["trailingActionClick"] }] } });
493
535
 
494
536
  let nextId$9 = 0;
495
537
  const SIZES$7 = {