@aceshooting/lyra-ui 0.1.0

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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/dist/components/combobox/combobox.d.ts +90 -0
  4. package/dist/components/combobox/combobox.js +398 -0
  5. package/dist/components/combobox/combobox.styles.d.ts +1 -0
  6. package/dist/components/combobox/combobox.styles.js +148 -0
  7. package/dist/components/combobox/option.d.ts +32 -0
  8. package/dist/components/combobox/option.js +62 -0
  9. package/dist/components/date-picker/calendar-core.d.ts +20 -0
  10. package/dist/components/date-picker/calendar-core.js +71 -0
  11. package/dist/components/date-picker/date-input.d.ts +57 -0
  12. package/dist/components/date-picker/date-input.js +233 -0
  13. package/dist/components/date-picker/date-input.styles.d.ts +1 -0
  14. package/dist/components/date-picker/date-input.styles.js +67 -0
  15. package/dist/components/date-picker/date-picker.d.ts +64 -0
  16. package/dist/components/date-picker/date-picker.js +310 -0
  17. package/dist/components/date-picker/date-picker.styles.d.ts +1 -0
  18. package/dist/components/date-picker/date-picker.styles.js +101 -0
  19. package/dist/components/flag/flag.d.ts +35 -0
  20. package/dist/components/flag/flag.js +91 -0
  21. package/dist/components/flag/flag.styles.d.ts +1 -0
  22. package/dist/components/flag/flag.styles.js +27 -0
  23. package/dist/components/flag/language-map.d.ts +11 -0
  24. package/dist/components/flag/language-map.js +62 -0
  25. package/dist/components/sparkline/sparkline.d.ts +30 -0
  26. package/dist/components/sparkline/sparkline.js +74 -0
  27. package/dist/components/sparkline/sparkline.styles.d.ts +1 -0
  28. package/dist/components/sparkline/sparkline.styles.js +31 -0
  29. package/dist/components/toast/toast-item.d.ts +49 -0
  30. package/dist/components/toast/toast-item.js +123 -0
  31. package/dist/components/toast/toast-item.styles.d.ts +1 -0
  32. package/dist/components/toast/toast-item.styles.js +81 -0
  33. package/dist/components/toast/toast.d.ts +32 -0
  34. package/dist/components/toast/toast.js +48 -0
  35. package/dist/components/toast/toast.styles.d.ts +1 -0
  36. package/dist/components/toast/toast.styles.js +52 -0
  37. package/dist/components/toast/toaster.d.ts +26 -0
  38. package/dist/components/toast/toaster.js +41 -0
  39. package/dist/internal/a11y.d.ts +4 -0
  40. package/dist/internal/a11y.js +18 -0
  41. package/dist/internal/form-associated.d.ts +26 -0
  42. package/dist/internal/form-associated.js +56 -0
  43. package/dist/internal/lyra-element.d.ts +11 -0
  44. package/dist/internal/lyra-element.js +21 -0
  45. package/dist/internal/positioner.d.ts +10 -0
  46. package/dist/internal/positioner.js +21 -0
  47. package/dist/internal/prefix.d.ts +4 -0
  48. package/dist/internal/prefix.js +8 -0
  49. package/dist/internal/tokens.styles.d.ts +1 -0
  50. package/dist/internal/tokens.styles.js +35 -0
  51. package/dist/lyra.d.ts +26 -0
  52. package/dist/lyra.js +23 -0
  53. package/package.json +64 -0
@@ -0,0 +1,18 @@
1
+ import { css } from 'lit';
2
+ let counter = 0;
3
+ /** Monotonic unique id, scoped by a short label (e.g. `nextId('listbox')`). */
4
+ export const nextId = (scope) => `lyra-${scope}-${++counter}`;
5
+ /** Visually-hidden-but-screen-reader-available helper class. */
6
+ export const srOnly = css `
7
+ .sr-only {
8
+ position: absolute;
9
+ width: 1px;
10
+ height: 1px;
11
+ padding: 0;
12
+ margin: -1px;
13
+ overflow: hidden;
14
+ clip: rect(0 0 0 0);
15
+ white-space: nowrap;
16
+ border: 0;
17
+ }
18
+ `;
@@ -0,0 +1,26 @@
1
+ import type { LitElement } from 'lit';
2
+ type Constructor<T> = new (...args: any[]) => T;
3
+ /** Public surface a `FormAssociated`-mixed element exposes to consumers and subclasses. */
4
+ export interface FormAssociatedInterface {
5
+ internals: ElementInternals;
6
+ name: string;
7
+ value: string;
8
+ disabled: boolean;
9
+ required: boolean;
10
+ setFormValue(next: string): void;
11
+ checkValidity(): boolean;
12
+ reportValidity(): boolean;
13
+ }
14
+ /**
15
+ * Mixin that turns a Lit component into a form-associated custom element via
16
+ * `ElementInternals`, so it participates in native `<form>` submission,
17
+ * validation, and reset — matching Web Awesome's free form controls.
18
+ *
19
+ * `value` uses a hand-written accessor (`noAccessor`) so `setFormValue` runs
20
+ * synchronously on assignment rather than on the async update cycle.
21
+ *
22
+ * The explicit return-type annotation is required so TypeScript can emit a
23
+ * declaration file for the (otherwise anonymous) mixin class (avoids TS4094).
24
+ */
25
+ export declare function FormAssociated<T extends Constructor<LitElement>>(Base: T): T & Constructor<FormAssociatedInterface>;
26
+ export {};
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Mixin that turns a Lit component into a form-associated custom element via
3
+ * `ElementInternals`, so it participates in native `<form>` submission,
4
+ * validation, and reset — matching Web Awesome's free form controls.
5
+ *
6
+ * `value` uses a hand-written accessor (`noAccessor`) so `setFormValue` runs
7
+ * synchronously on assignment rather than on the async update cycle.
8
+ *
9
+ * The explicit return-type annotation is required so TypeScript can emit a
10
+ * declaration file for the (otherwise anonymous) mixin class (avoids TS4094).
11
+ */
12
+ export function FormAssociated(Base) {
13
+ class FormAssociatedElement extends Base {
14
+ static { this.formAssociated = true; }
15
+ static { this.properties = {
16
+ name: {},
17
+ value: { noAccessor: true },
18
+ disabled: { type: Boolean, reflect: true },
19
+ required: { type: Boolean, reflect: true },
20
+ }; }
21
+ constructor(...args) {
22
+ super(...args);
23
+ this.name = '';
24
+ this.disabled = false;
25
+ this.required = false;
26
+ this._value = '';
27
+ this.internals = this.attachInternals();
28
+ }
29
+ get value() {
30
+ return this._value;
31
+ }
32
+ set value(next) {
33
+ const old = this._value;
34
+ this._value = next ?? '';
35
+ this.internals.setFormValue(this._value);
36
+ this.requestUpdate('value', old);
37
+ }
38
+ /** Programmatically set the submitted value (alias kept for clarity). */
39
+ setFormValue(next) {
40
+ this.value = next;
41
+ }
42
+ checkValidity() {
43
+ return this.internals.checkValidity();
44
+ }
45
+ reportValidity() {
46
+ return this.internals.reportValidity();
47
+ }
48
+ formResetCallback() {
49
+ this.value = '';
50
+ }
51
+ formDisabledCallback(disabled) {
52
+ this.disabled = disabled;
53
+ }
54
+ }
55
+ return FormAssociatedElement;
56
+ }
@@ -0,0 +1,11 @@
1
+ import { LitElement, type CSSResultGroup } from 'lit';
2
+ /**
3
+ * Shared base for every Lyra component. Supplies the design-token layer
4
+ * (Web Awesome `--wa-*` tokens with `--lyra-*` fallbacks). RTL is handled by
5
+ * components using CSS logical properties rather than a forced `dir`.
6
+ */
7
+ export declare class LyraElement extends LitElement {
8
+ static styles: CSSResultGroup;
9
+ /** Dispatch a composed, bubbling `lyra-*` custom event. */
10
+ protected emit<T = unknown>(name: string, detail?: T): CustomEvent<T>;
11
+ }
@@ -0,0 +1,21 @@
1
+ import { LitElement } from 'lit';
2
+ import { tokens } from './tokens.styles.js';
3
+ /**
4
+ * Shared base for every Lyra component. Supplies the design-token layer
5
+ * (Web Awesome `--wa-*` tokens with `--lyra-*` fallbacks). RTL is handled by
6
+ * components using CSS logical properties rather than a forced `dir`.
7
+ */
8
+ export class LyraElement extends LitElement {
9
+ static { this.styles = [tokens]; }
10
+ /** Dispatch a composed, bubbling `lyra-*` custom event. */
11
+ emit(name, detail) {
12
+ const event = new CustomEvent(name, {
13
+ detail: detail,
14
+ bubbles: true,
15
+ composed: true,
16
+ cancelable: true,
17
+ });
18
+ this.dispatchEvent(event);
19
+ return event;
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ import { type Placement } from '@floating-ui/dom';
2
+ export interface PlaceOptions {
3
+ placement?: Placement;
4
+ offset?: number;
5
+ }
6
+ /**
7
+ * Position `popup` (fixed) relative to `anchor` with flip/shift, keeping it
8
+ * updated on scroll/resize. Returns a cleanup function that stops updating.
9
+ */
10
+ export declare function place(anchor: HTMLElement, popup: HTMLElement, opts?: PlaceOptions): () => void;
@@ -0,0 +1,21 @@
1
+ import { computePosition, autoUpdate, flip, shift, offset, } from '@floating-ui/dom';
2
+ /**
3
+ * Position `popup` (fixed) relative to `anchor` with flip/shift, keeping it
4
+ * updated on scroll/resize. Returns a cleanup function that stops updating.
5
+ */
6
+ export function place(anchor, popup, opts = {}) {
7
+ popup.style.position = 'fixed';
8
+ popup.style.margin = '0';
9
+ const update = () => computePosition(anchor, popup, {
10
+ // The popup is `position: fixed`, so Floating UI must compute viewport-relative
11
+ // coordinates; without this it defaults to 'absolute' and the popup lands off by
12
+ // the scroll offset (appears too far down on a scrolled page).
13
+ strategy: 'fixed',
14
+ placement: opts.placement ?? 'bottom-start',
15
+ middleware: [offset(opts.offset ?? 4), flip(), shift({ padding: 8 })],
16
+ }).then(({ x, y }) => {
17
+ popup.style.left = `${x}px`;
18
+ popup.style.top = `${y}px`;
19
+ });
20
+ return autoUpdate(anchor, popup, update);
21
+ }
@@ -0,0 +1,4 @@
1
+ export declare const LYRA_PREFIX = "lyra";
2
+ export declare const tag: (name: string) => string;
3
+ /** Idempotent registration — safe if a module is imported twice. */
4
+ export declare function defineElement(name: string, ctor: CustomElementConstructor): void;
@@ -0,0 +1,8 @@
1
+ export const LYRA_PREFIX = 'lyra';
2
+ export const tag = (name) => `${LYRA_PREFIX}-${name}`;
3
+ /** Idempotent registration — safe if a module is imported twice. */
4
+ export function defineElement(name, ctor) {
5
+ const t = tag(name);
6
+ if (!customElements.get(t))
7
+ customElements.define(t, ctor);
8
+ }
@@ -0,0 +1 @@
1
+ export declare const tokens: import("lit").CSSResult;
@@ -0,0 +1,35 @@
1
+ import { css } from 'lit';
2
+ // Every design value references a Web Awesome token with a --lyra-* fallback,
3
+ // so components look native inside a WA app and still render standalone.
4
+ export const tokens = css `
5
+ :host {
6
+ --lyra-color-surface: var(--wa-color-surface-default, #fff);
7
+ --lyra-color-text: var(--wa-color-text-normal, #1a1a1a);
8
+ --lyra-color-text-quiet: var(--wa-color-text-quiet, #6b7280);
9
+ --lyra-color-border: var(--wa-color-neutral-fill-normal, #d4d4d8);
10
+ --lyra-color-brand: var(--wa-color-brand-fill-loud, #0969da);
11
+ --lyra-color-brand-quiet: var(--wa-color-brand-fill-quiet, #ddf4ff);
12
+ --lyra-color-success: var(--wa-color-success-fill-loud, #1a7f37);
13
+ --lyra-color-warning: var(--wa-color-warning-fill-loud, #9a6700);
14
+ --lyra-color-danger: var(--wa-color-danger-fill-loud, #cf222e);
15
+ --lyra-space-xs: var(--wa-space-xs, 0.25rem);
16
+ --lyra-space-s: var(--wa-space-s, 0.5rem);
17
+ --lyra-space-m: var(--wa-space-m, 0.75rem);
18
+ --lyra-space-l: var(--wa-space-l, 1rem);
19
+ --lyra-radius: var(--wa-border-radius-m, 0.375rem);
20
+ --lyra-shadow: var(--wa-shadow-m, 0 2px 8px rgb(0 0 0 / 0.15));
21
+ --lyra-font: var(--wa-font-family-body, system-ui, sans-serif);
22
+
23
+ font-family: var(--lyra-font);
24
+ color: var(--lyra-color-text);
25
+ box-sizing: border-box;
26
+ }
27
+ :host([hidden]) {
28
+ display: none !important;
29
+ }
30
+ *,
31
+ *::before,
32
+ *::after {
33
+ box-sizing: inherit;
34
+ }
35
+ `;
package/dist/lyra.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import './components/sparkline/sparkline.js';
2
+ import './components/toast/toast.js';
3
+ import './components/toast/toast-item.js';
4
+ import './components/combobox/combobox.js';
5
+ import './components/combobox/option.js';
6
+ import './components/date-picker/date-picker.js';
7
+ import './components/date-picker/date-input.js';
8
+ import './components/flag/flag.js';
9
+ export { LyraSparkline } from './components/sparkline/sparkline.js';
10
+ export { LyraToast } from './components/toast/toast.js';
11
+ export type { ToastPlacement, ToastCreateOptions } from './components/toast/toast.js';
12
+ export { LyraToastItem } from './components/toast/toast-item.js';
13
+ export type { ToastVariant, ToastSize } from './components/toast/toast-item.js';
14
+ export { toast } from './components/toast/toaster.js';
15
+ export type { ToastOptions, ToastHandle } from './components/toast/toaster.js';
16
+ export { LyraCombobox } from './components/combobox/combobox.js';
17
+ export type { OptionFilter } from './components/combobox/combobox.js';
18
+ export { LyraOption } from './components/combobox/option.js';
19
+ export { LyraDatePicker } from './components/date-picker/date-picker.js';
20
+ export type { DateRange } from './components/date-picker/date-picker.js';
21
+ export { LyraDateInput } from './components/date-picker/date-input.js';
22
+ export { LyraFlag } from './components/flag/flag.js';
23
+ export { LANGUAGE_TO_COUNTRY, languageToCountry } from './components/flag/language-map.js';
24
+ export { LyraElement } from './internal/lyra-element.js';
25
+ export { FormAssociated } from './internal/form-associated.js';
26
+ export { LYRA_PREFIX, tag, defineElement } from './internal/prefix.js';
package/dist/lyra.js ADDED
@@ -0,0 +1,23 @@
1
+ // Side-effect imports register every component…
2
+ import './components/sparkline/sparkline.js';
3
+ import './components/toast/toast.js';
4
+ import './components/toast/toast-item.js';
5
+ import './components/combobox/combobox.js';
6
+ import './components/combobox/option.js';
7
+ import './components/date-picker/date-picker.js';
8
+ import './components/date-picker/date-input.js';
9
+ import './components/flag/flag.js';
10
+ // …and the barrel re-exports classes, helpers, and types.
11
+ export { LyraSparkline } from './components/sparkline/sparkline.js';
12
+ export { LyraToast } from './components/toast/toast.js';
13
+ export { LyraToastItem } from './components/toast/toast-item.js';
14
+ export { toast } from './components/toast/toaster.js';
15
+ export { LyraCombobox } from './components/combobox/combobox.js';
16
+ export { LyraOption } from './components/combobox/option.js';
17
+ export { LyraDatePicker } from './components/date-picker/date-picker.js';
18
+ export { LyraDateInput } from './components/date-picker/date-input.js';
19
+ export { LyraFlag } from './components/flag/flag.js';
20
+ export { LANGUAGE_TO_COUNTRY, languageToCountry } from './components/flag/language-map.js';
21
+ export { LyraElement } from './internal/lyra-element.js';
22
+ export { FormAssociated } from './internal/form-associated.js';
23
+ export { LYRA_PREFIX, tag, defineElement } from './internal/prefix.js';
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@aceshooting/lyra-ui",
3
+ "version": "0.1.0",
4
+ "description": "Free, clean-room Lit web components — a companion to Web Awesome.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "author": {
8
+ "name": "Aceshooting",
9
+ "email": "info@aceshooting.com"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/aceshooting/lyra-ui.git",
14
+ "directory": "packages/lyra-ui"
15
+ },
16
+ "homepage": "https://github.com/aceshooting/lyra-ui#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/aceshooting/lyra-ui/issues"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "exports": {
27
+ ".": "./dist/lyra.js",
28
+ "./components/*": "./dist/components/*",
29
+ "./internal/*": "./dist/internal/*"
30
+ },
31
+ "sideEffects": [
32
+ "**/components/**/*.js",
33
+ "./dist/lyra.js"
34
+ ],
35
+ "dependencies": {
36
+ "lit": "^3.2.0",
37
+ "@floating-ui/dom": "^1.6.0"
38
+ },
39
+ "peerDependencies": {
40
+ "@aceshooting/lyra-flags": "^0.1.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "@aceshooting/lyra-flags": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "devDependencies": {
48
+ "typescript": "^5.6.0",
49
+ "@web/test-runner": "^0.19.0",
50
+ "@web/test-runner-playwright": "^0.11.0",
51
+ "@web/dev-server-esbuild": "^1.0.2",
52
+ "@open-wc/testing": "^4.0.0",
53
+ "@custom-elements-manifest/analyzer": "^0.10.0",
54
+ "@aceshooting/lyra-flags": "0.1.0"
55
+ },
56
+ "customElements": "custom-elements.json",
57
+ "scripts": {
58
+ "build": "tsc -p tsconfig.json",
59
+ "test": "wtr",
60
+ "test:watch": "wtr --watch",
61
+ "manifest": "cem analyze --litelement --outdir .",
62
+ "lint": "tsc --noEmit -p tsconfig.json"
63
+ }
64
+ }