@alishenriques/design-system 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -28,6 +28,19 @@ yarn dev # build em watch
28
28
 
29
29
  ## Componentes
30
30
 
31
+ - `Avatar` — foto circular que expande em overlay (zoom, blur no fundo, fecha no ×/Escape/clique fora)
31
32
  - `Button` (`primary`, `ghost`)
33
+ - `CommandPalette` — busca/atalhos em overlay (⌘K)
34
+ - `Eyebrow` — rótulo pequeno em maiúsculas
35
+ - `LoadingButton` — botão com estado de carregamento embutido (`isLoading`, `loadingText`)
36
+ - `Panel` — superfície elevada com borda, com fundo em grade de pontos opcional
37
+ - `PipelineBadges` — chips estilo pipeline de CI
38
+ - `StatGrid` — grade de estatísticas
39
+ - `TagList` — lista de tags
40
+ - `TerminalPrompt` — linha de prompt de terminal com cursor piscando
32
41
 
33
42
  Estilos via CSS Modules e tokens `--ds-*` (`src/tokens.css`).
43
+
44
+ ## Convenção: quando um componente entra aqui
45
+
46
+ Qualquer componente **reaproveitável em mais de um contexto** — não amarrado a uma marca, texto ou dado específico de um produto — nasce **aqui**, não direto no app consumidor: props dinâmicas (nunca texto/comportamento fixo), componente desacoplado (sem depender de dado externo específico de um app) e sempre com testes unitários. `alis-portfolio` só importa e consome; ele não duplica esses componentes localmente. Exemplo: `LoadingButton` e `Avatar` nasceram de necessidades do portfólio, mas como nada neles é específico do portfólio (o texto de carregamento e o rótulo do botão de fechar são props), vivem aqui. Já `Logo` (a marca do Alisson) e `LoadingOverlay` (que usa esse `Logo` internamente) ficam no `alis-portfolio`, por serem específicos daquele produto.
@@ -0,0 +1,24 @@
1
+ import { ButtonHTMLAttributes } from 'react';
2
+ export type AvatarProps = {
3
+ /** Image URL. */
4
+ src: string;
5
+ /** Accessible name for the photo — used for both the trigger and the expanded dialog. */
6
+ alt: string;
7
+ /** Diameter of the collapsed circular thumbnail, in px. Default: 96. */
8
+ size?: number;
9
+ /** Any valid CSS size for the expanded photo. Default: "min(70vw, 60vh, 440px)". */
10
+ expandedSize?: string;
11
+ /**
12
+ * CSS `object-position` for the crop, in both states — e.g. "top" when a
13
+ * centred crop clips the subject's head. Default: "center".
14
+ */
15
+ objectPosition?: string;
16
+ /** Accessible label for the × button that closes the expanded photo. Default: "Close". */
17
+ closeLabel?: string;
18
+ } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "type" | "onClick">;
19
+ /**
20
+ * A circular photo that expands into a large, centred, blurred-backdrop
21
+ * overlay on click — the same round crop, just bigger, with a zoom-in
22
+ * transition. Closed by the × button, a backdrop click, or Escape.
23
+ */
24
+ export declare function Avatar({ src, alt, size, expandedSize, objectPosition, closeLabel, className, ...props }: AvatarProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { Avatar } from './Avatar';
2
+ export type { AvatarProps } from './Avatar';
@@ -0,0 +1,29 @@
1
+ import { ButtonHTMLAttributes, ReactNode } from 'react';
2
+ export type LoadingButtonProps = {
3
+ /** Shows the loading treatment instead of `children`, and disables the button while true. */
4
+ isLoading: boolean;
5
+ /**
6
+ * The word shown after "$" while loading (e.g. "sending"). Not translated
7
+ * by this component — pass an already-localised string, so every caller
8
+ * can phrase it for its own action instead of a hardcoded label.
9
+ */
10
+ loadingText: string;
11
+ children: ReactNode;
12
+ } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children">;
13
+ /**
14
+ * A button with a built-in, terminal-styled loading state: while `isLoading`,
15
+ * it goes dark with an accent border and its label becomes "$ {loadingText}"
16
+ * with a blinking block cursor — feedback right on the button, as an
17
+ * alternative to a full-screen loading overlay for actions with a natural,
18
+ * local place to show progress (a form's submit button is the first user).
19
+ *
20
+ * Idle appearance (colour, padding, icon) is entirely up to the consumer's
21
+ * own `className`/`style`/`children`; this component only overlays the
22
+ * loading look on top, and only while `isLoading` is true, so it works for
23
+ * any button in any host app. That override is applied via inline styles,
24
+ * not a CSS class: a consumer's own stylesheet (Tailwind, CSS Modules,
25
+ * anything) could be bundled either side of this package's CSS, so a
26
+ * class-based override can't reliably win the cascade — inline styles always
27
+ * do, short of the consumer using `!important`.
28
+ */
29
+ export declare function LoadingButton({ isLoading, loadingText, children, className, style, disabled, type, ...props }: LoadingButtonProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { LoadingButton } from './LoadingButton';
2
+ export type { LoadingButtonProps } from './LoadingButton';
@@ -1 +1 @@
1
- :root{--ds-color-bg: #0b0b0f;--ds-color-bg-raised: #131318;--ds-color-fg: #f4f1ea;--ds-color-muted: #9a958c;--ds-color-accent: #c8ff00;--ds-color-accent-ink: #111111;--ds-color-accent-soft: rgba(200, 255, 0, .1);--ds-color-border: rgba(244, 241, 234, .1);--ds-color-border-strong: rgba(244, 241, 234, .16);--ds-radius-sm: 8px;--ds-radius-md: 16px;--ds-space-1: .25rem;--ds-space-2: .5rem;--ds-space-3: .75rem;--ds-space-4: 1rem;--ds-space-5: 1.5rem;--ds-space-6: 2rem;--ds-space-8: 3rem;--ds-font-sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;--ds-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;--ds-font-display: "Archivo", system-ui, -apple-system, sans-serif;--ds-motion-fast: .18s cubic-bezier(.22, 1, .36, 1)}.ds-dot-grid{background-image:radial-gradient(circle at 1px 1px,var(--ds-color-border-strong) 1px,transparent 0);background-size:22px 22px}._button_1jhtl_1{display:inline-flex;align-items:center;justify-content:center;gap:var(--ds-space-2);border:0;border-radius:var(--ds-radius-sm);padding:var(--ds-space-3) var(--ds-space-4);font-family:var(--ds-font-sans);font-weight:600;letter-spacing:.01em;cursor:pointer;transition:transform var(--ds-motion-fast),background-color var(--ds-motion-fast),box-shadow var(--ds-motion-fast)}._button_1jhtl_1:hover{transform:translateY(-1px)}._button_1jhtl_1:active{transform:translateY(0)}._button_1jhtl_1:disabled{cursor:not-allowed;opacity:.5;transform:none}._primary_1jhtl_33{background:var(--ds-color-accent);color:var(--ds-color-accent-ink);box-shadow:0 0 0 0 transparent}._primary_1jhtl_33:hover:not(:disabled){box-shadow:0 8px 24px color-mix(in srgb,var(--ds-color-accent) 35%,transparent)}._ghost_1jhtl_43{background:transparent;color:var(--ds-color-fg);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ds-color-fg) 22%,transparent)}._trigger_10bud_1{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--ds-color-border-strong);background:var(--ds-color-bg-raised);color:var(--ds-color-muted);padding:7px 12px;border-radius:8px;cursor:pointer;font-family:var(--ds-font-mono);font-size:12px;white-space:nowrap;transition:color var(--ds-motion-fast),border-color var(--ds-motion-fast)}._trigger_10bud_1:hover,._trigger_10bud_1:focus-visible{color:var(--ds-color-fg);border-color:var(--ds-color-accent)}._kbd_10bud_23{background:var(--ds-color-bg);border:1px solid var(--ds-color-border-strong);border-radius:4px;padding:1px 5px;font-family:var(--ds-font-mono)}._backdrop_10bud_31{position:fixed;inset:0;background:#0b0b0fb3;display:flex;align-items:flex-start;justify-content:center;padding:14vh 16px 16px;z-index:100}._dialog_10bud_42{width:100%;max-width:520px;background:var(--ds-color-bg-raised);border:1px solid var(--ds-color-border-strong);border-radius:12px;overflow:hidden;font-family:var(--ds-font-mono);box-shadow:0 20px 60px #00000080}._input_10bud_53{width:100%;background:transparent;border:0;border-bottom:1px solid var(--ds-color-border);color:var(--ds-color-fg);padding:16px 18px;font-family:var(--ds-font-mono);font-size:14px;outline:none}._input_10bud_53::placeholder{color:var(--ds-color-muted)}._list_10bud_69{list-style:none;margin:0;padding:8px;max-height:280px;overflow:auto}._list_10bud_69 a{display:flex;justify-content:space-between;gap:10px;padding:10px 12px;border-radius:8px;text-decoration:none;color:var(--ds-color-fg);font-size:13px}._list_10bud_69 a:hover,._list_10bud_69 a:focus-visible{background:var(--ds-color-accent-soft);color:var(--ds-color-accent)}._list_10bud_69 small{color:var(--ds-color-muted);font-size:11px}._eyebrow_1a4gy_1{margin:0;font-family:var(--ds-font-mono);font-weight:500;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--ds-color-muted)}._panel_m16j3_1{position:relative;border:1px solid var(--ds-color-border);border-radius:var(--ds-radius-md);background:var(--ds-color-bg-raised);padding:clamp(28px,5vw,64px)}._list_27va3_1{display:flex;flex-wrap:wrap;gap:var(--ds-space-2);margin:0;padding:0;list-style:none;font-family:var(--ds-font-mono);font-size:12px}._step_27va3_12{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--ds-color-border-strong);border-radius:6px;padding:6px 10px;color:var(--ds-color-muted)}._step_27va3_12 b{color:var(--ds-color-accent);font-weight:600}._grid_94gwu_1{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;margin:0;background:var(--ds-color-border);border:1px solid var(--ds-color-border);border-radius:10px;overflow:hidden}._cell_94gwu_12{background:var(--ds-color-bg-raised);padding:var(--ds-space-4);display:flex;flex-direction:column-reverse}._value_94gwu_19{margin:0;font-family:var(--ds-font-mono);font-weight:700;font-size:22px;color:var(--ds-color-fg);font-variant-numeric:tabular-nums}._label_94gwu_28{font-family:var(--ds-font-mono);font-size:11px;color:var(--ds-color-muted);text-transform:uppercase;letter-spacing:.04em}._list_17qxg_1{display:flex;flex-wrap:wrap;gap:var(--ds-space-2);margin:0;padding:0;list-style:none}._tag_17qxg_10{font-family:var(--ds-font-mono);font-size:12px;color:var(--ds-color-fg);border:1px solid var(--ds-color-border-strong);border-radius:999px;padding:6px 12px}._prompt_vxkw7_1{margin:0;display:flex;align-items:center;gap:2px;font-family:var(--ds-font-mono);font-size:13px;color:var(--ds-color-accent)}._path_vxkw7_11{color:var(--ds-color-muted)}._cursor_vxkw7_15{display:inline-block;width:7px;height:15px;margin-left:2px;background:var(--ds-color-accent);animation:_blink_vxkw7_1 1.1s step-end infinite}@media(prefers-reduced-motion:reduce){._cursor_vxkw7_15{animation:none;opacity:.7}}@keyframes _blink_vxkw7_1{50%{opacity:0}}
1
+ :root{--ds-color-bg: #0b0b0f;--ds-color-bg-raised: #131318;--ds-color-fg: #f4f1ea;--ds-color-muted: #9a958c;--ds-color-accent: #c8ff00;--ds-color-accent-ink: #111111;--ds-color-accent-soft: rgba(200, 255, 0, .1);--ds-color-border: rgba(244, 241, 234, .1);--ds-color-border-strong: rgba(244, 241, 234, .16);--ds-radius-sm: 8px;--ds-radius-md: 16px;--ds-space-1: .25rem;--ds-space-2: .5rem;--ds-space-3: .75rem;--ds-space-4: 1rem;--ds-space-5: 1.5rem;--ds-space-6: 2rem;--ds-space-8: 3rem;--ds-font-sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;--ds-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;--ds-font-display: "Archivo", system-ui, -apple-system, sans-serif;--ds-motion-fast: .18s cubic-bezier(.22, 1, .36, 1)}.ds-dot-grid{background-image:radial-gradient(circle at 1px 1px,var(--ds-color-border-strong) 1px,transparent 0);background-size:22px 22px}._trigger_e3bgf_1{display:inline-flex;padding:0;border:2px solid var(--ds-color-accent);border-radius:50%;overflow:hidden;cursor:pointer;background:var(--ds-color-bg-raised);transition:transform var(--ds-motion-fast),box-shadow var(--ds-motion-fast)}._trigger_e3bgf_1:hover,._trigger_e3bgf_1:focus-visible{transform:scale(1.03);outline:none;box-shadow:0 0 0 4px var(--ds-color-accent-soft)}._image_e3bgf_19{width:100%;height:100%;object-fit:cover;display:block}._backdrop_e3bgf_26{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;padding:24px;background:#0b0b0fb8;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);opacity:0;transition:opacity .22s ease-out}._backdropVisible_e3bgf_48{opacity:1}._frame_e3bgf_55{position:relative;opacity:0;transition:opacity .26s ease-out}._frameVisible_e3bgf_61{opacity:1}._circle_e3bgf_53{position:absolute;inset:0;border-radius:50%;overflow:hidden;border:3px solid var(--ds-color-accent);box-shadow:0 20px 60px #00000080;transform:scale(.85);transition:transform .26s cubic-bezier(.22,1,.36,1)}._frameVisible_e3bgf_61 ._circle_e3bgf_53{transform:scale(1)}._expandedImage_e3bgf_80{width:100%;height:100%;object-fit:cover;display:block}._closeButton_e3bgf_87{position:absolute;top:-10px;right:-10px;display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;border:1px solid var(--ds-color-border-strong);background:var(--ds-color-bg-raised);color:var(--ds-color-fg);font-size:20px;line-height:1;cursor:pointer;transition:border-color var(--ds-motion-fast),color var(--ds-motion-fast)}._closeButton_e3bgf_87:hover,._closeButton_e3bgf_87:focus-visible{border-color:var(--ds-color-accent);color:var(--ds-color-accent);outline:none}@media(prefers-reduced-motion:reduce){._backdrop_e3bgf_26,._frame_e3bgf_55,._circle_e3bgf_53{transition:none}}._button_1jhtl_1{display:inline-flex;align-items:center;justify-content:center;gap:var(--ds-space-2);border:0;border-radius:var(--ds-radius-sm);padding:var(--ds-space-3) var(--ds-space-4);font-family:var(--ds-font-sans);font-weight:600;letter-spacing:.01em;cursor:pointer;transition:transform var(--ds-motion-fast),background-color var(--ds-motion-fast),box-shadow var(--ds-motion-fast)}._button_1jhtl_1:hover{transform:translateY(-1px)}._button_1jhtl_1:active{transform:translateY(0)}._button_1jhtl_1:disabled{cursor:not-allowed;opacity:.5;transform:none}._primary_1jhtl_33{background:var(--ds-color-accent);color:var(--ds-color-accent-ink);box-shadow:0 0 0 0 transparent}._primary_1jhtl_33:hover:not(:disabled){box-shadow:0 8px 24px color-mix(in srgb,var(--ds-color-accent) 35%,transparent)}._ghost_1jhtl_43{background:transparent;color:var(--ds-color-fg);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ds-color-fg) 22%,transparent)}._trigger_10bud_1{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--ds-color-border-strong);background:var(--ds-color-bg-raised);color:var(--ds-color-muted);padding:7px 12px;border-radius:8px;cursor:pointer;font-family:var(--ds-font-mono);font-size:12px;white-space:nowrap;transition:color var(--ds-motion-fast),border-color var(--ds-motion-fast)}._trigger_10bud_1:hover,._trigger_10bud_1:focus-visible{color:var(--ds-color-fg);border-color:var(--ds-color-accent)}._kbd_10bud_23{background:var(--ds-color-bg);border:1px solid var(--ds-color-border-strong);border-radius:4px;padding:1px 5px;font-family:var(--ds-font-mono)}._backdrop_10bud_31{position:fixed;inset:0;background:#0b0b0fb3;display:flex;align-items:flex-start;justify-content:center;padding:14vh 16px 16px;z-index:100}._dialog_10bud_42{width:100%;max-width:520px;background:var(--ds-color-bg-raised);border:1px solid var(--ds-color-border-strong);border-radius:12px;overflow:hidden;font-family:var(--ds-font-mono);box-shadow:0 20px 60px #00000080}._input_10bud_53{width:100%;background:transparent;border:0;border-bottom:1px solid var(--ds-color-border);color:var(--ds-color-fg);padding:16px 18px;font-family:var(--ds-font-mono);font-size:14px;outline:none}._input_10bud_53::placeholder{color:var(--ds-color-muted)}._list_10bud_69{list-style:none;margin:0;padding:8px;max-height:280px;overflow:auto}._list_10bud_69 a{display:flex;justify-content:space-between;gap:10px;padding:10px 12px;border-radius:8px;text-decoration:none;color:var(--ds-color-fg);font-size:13px}._list_10bud_69 a:hover,._list_10bud_69 a:focus-visible{background:var(--ds-color-accent-soft);color:var(--ds-color-accent)}._list_10bud_69 small{color:var(--ds-color-muted);font-size:11px}._eyebrow_1a4gy_1{margin:0;font-family:var(--ds-font-mono);font-weight:500;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--ds-color-muted)}._loadingLabel_1yug9_1{display:flex;align-items:center;justify-content:center;gap:4px;font-family:var(--ds-font-mono);text-transform:lowercase}._cursor_1yug9_10{display:inline-block;width:7px;height:14px;background:var(--ds-color-accent);animation:_blink_1yug9_1 1s step-end infinite}@media(prefers-reduced-motion:reduce){._cursor_1yug9_10{animation:none}}@keyframes _blink_1yug9_1{50%{opacity:0}}._panel_m16j3_1{position:relative;border:1px solid var(--ds-color-border);border-radius:var(--ds-radius-md);background:var(--ds-color-bg-raised);padding:clamp(28px,5vw,64px)}._list_27va3_1{display:flex;flex-wrap:wrap;gap:var(--ds-space-2);margin:0;padding:0;list-style:none;font-family:var(--ds-font-mono);font-size:12px}._step_27va3_12{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--ds-color-border-strong);border-radius:6px;padding:6px 10px;color:var(--ds-color-muted)}._step_27va3_12 b{color:var(--ds-color-accent);font-weight:600}._grid_94gwu_1{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;margin:0;background:var(--ds-color-border);border:1px solid var(--ds-color-border);border-radius:10px;overflow:hidden}._cell_94gwu_12{background:var(--ds-color-bg-raised);padding:var(--ds-space-4);display:flex;flex-direction:column-reverse}._value_94gwu_19{margin:0;font-family:var(--ds-font-mono);font-weight:700;font-size:22px;color:var(--ds-color-fg);font-variant-numeric:tabular-nums}._label_94gwu_28{font-family:var(--ds-font-mono);font-size:11px;color:var(--ds-color-muted);text-transform:uppercase;letter-spacing:.04em}._list_17qxg_1{display:flex;flex-wrap:wrap;gap:var(--ds-space-2);margin:0;padding:0;list-style:none}._tag_17qxg_10{font-family:var(--ds-font-mono);font-size:12px;color:var(--ds-color-fg);border:1px solid var(--ds-color-border-strong);border-radius:999px;padding:6px 12px}._prompt_vxkw7_1{margin:0;display:flex;align-items:center;gap:2px;font-family:var(--ds-font-mono);font-size:13px;color:var(--ds-color-accent)}._path_vxkw7_11{color:var(--ds-color-muted)}._cursor_vxkw7_15{display:inline-block;width:7px;height:15px;margin-left:2px;background:var(--ds-color-accent);animation:_blink_vxkw7_1 1.1s step-end infinite}@media(prefers-reduced-motion:reduce){._cursor_vxkw7_15{animation:none;opacity:.7}}@keyframes _blink_vxkw7_1{50%{opacity:0}}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,13 @@
1
+ export { Avatar } from './components/Avatar';
2
+ export type { AvatarProps } from './components/Avatar';
1
3
  export { Button } from './components/Button';
2
4
  export type { ButtonProps, ButtonVariant } from './components/Button';
3
5
  export { CommandPalette } from './components/CommandPalette';
4
6
  export type { CommandPaletteItem, CommandPaletteProps } from './components/CommandPalette';
5
7
  export { Eyebrow } from './components/Eyebrow';
6
8
  export type { EyebrowProps } from './components/Eyebrow';
9
+ export { LoadingButton } from './components/LoadingButton';
10
+ export type { LoadingButtonProps } from './components/LoadingButton';
7
11
  export { Panel } from './components/Panel';
8
12
  export type { PanelProps } from './components/Panel';
9
13
  export { PipelineBadges } from './components/PipelineBadges';
package/dist/index.js CHANGED
@@ -1,152 +1,282 @@
1
1
  "use client";
2
- import { jsx as e, jsxs as r, Fragment as $ } from "react/jsx-runtime";
3
- import { useState as f, useRef as B, useEffect as g } from "react";
4
- const x = "_button_1jhtl_1", L = "_primary_1jhtl_33", E = "_ghost_1jhtl_43", y = {
5
- button: x,
6
- primary: L,
7
- ghost: E
2
+ import { jsxs as r, Fragment as E, jsx as e } from "react/jsx-runtime";
3
+ import { useState as k, useEffect as B, useRef as D } from "react";
4
+ const T = "_trigger_e3bgf_1", A = "_image_e3bgf_19", I = "_backdrop_e3bgf_26", S = "_backdropVisible_e3bgf_48", F = "_frame_e3bgf_55", K = "_frameVisible_e3bgf_61", q = "_circle_e3bgf_53", P = "_expandedImage_e3bgf_80", O = "_closeButton_e3bgf_87", d = {
5
+ trigger: T,
6
+ image: A,
7
+ backdrop: I,
8
+ backdropVisible: S,
9
+ frame: F,
10
+ frameVisible: K,
11
+ circle: q,
12
+ expandedImage: P,
13
+ closeButton: O
14
+ }, R = 96, U = "min(70vw, 60vh, 440px)";
15
+ function he({
16
+ src: t,
17
+ alt: a,
18
+ size: l = R,
19
+ expandedSize: n = U,
20
+ objectPosition: s = "center",
21
+ closeLabel: c = "Close",
22
+ className: m,
23
+ ...i
24
+ }) {
25
+ const [u, b] = k(!1), [f, h] = k(!1);
26
+ B(() => {
27
+ if (!u) return;
28
+ function p(V) {
29
+ V.key === "Escape" && b(!1);
30
+ }
31
+ document.addEventListener("keydown", p);
32
+ const N = document.body.style.overflow;
33
+ document.body.style.overflow = "hidden";
34
+ const L = requestAnimationFrame(() => h(!0));
35
+ return () => {
36
+ document.removeEventListener("keydown", p), document.body.style.overflow = N, cancelAnimationFrame(L), h(!1);
37
+ };
38
+ }, [u]);
39
+ const v = [d.trigger, m].filter(Boolean).join(" "), o = [d.frame, f && d.frameVisible].filter(Boolean).join(" "), _ = [d.backdrop, f && d.backdropVisible].filter(Boolean).join(" ");
40
+ return /* @__PURE__ */ r(E, { children: [
41
+ /* @__PURE__ */ e(
42
+ "button",
43
+ {
44
+ type: "button",
45
+ className: v,
46
+ style: { width: l, height: l },
47
+ onClick: () => b(!0),
48
+ "aria-haspopup": "dialog",
49
+ ...i,
50
+ children: /* @__PURE__ */ e(
51
+ "img",
52
+ {
53
+ src: t,
54
+ alt: a,
55
+ className: d.image,
56
+ style: { objectPosition: s },
57
+ loading: "lazy"
58
+ }
59
+ )
60
+ }
61
+ ),
62
+ u && /* @__PURE__ */ e("div", { className: _, onClick: (p) => p.target === p.currentTarget && b(!1), children: /* @__PURE__ */ r(
63
+ "div",
64
+ {
65
+ className: o,
66
+ style: { width: n, height: n },
67
+ role: "dialog",
68
+ "aria-modal": "true",
69
+ "aria-label": a,
70
+ children: [
71
+ /* @__PURE__ */ e("div", { className: d.circle, children: /* @__PURE__ */ e(
72
+ "img",
73
+ {
74
+ src: t,
75
+ alt: a,
76
+ className: d.expandedImage,
77
+ style: { objectPosition: s }
78
+ }
79
+ ) }),
80
+ /* @__PURE__ */ e(
81
+ "button",
82
+ {
83
+ type: "button",
84
+ className: d.closeButton,
85
+ onClick: () => b(!1),
86
+ "aria-label": c,
87
+ children: "×"
88
+ }
89
+ )
90
+ ]
91
+ }
92
+ ) })
93
+ ] });
94
+ }
95
+ const Z = "_button_1jhtl_1", G = "_primary_1jhtl_33", Q = "_ghost_1jhtl_43", C = {
96
+ button: Z,
97
+ primary: G,
98
+ ghost: Q
8
99
  };
9
- function te({
10
- children: n,
11
- variant: s = "primary",
12
- type: a = "button",
13
- className: o,
14
- ...t
100
+ function ye({
101
+ children: t,
102
+ variant: a = "primary",
103
+ type: l = "button",
104
+ className: n,
105
+ ...s
15
106
  }) {
16
- const u = [y.button, y[s], o].filter(Boolean).join(" ");
17
- return /* @__PURE__ */ e("button", { type: a, className: u, "data-variant": s, ...t, children: n });
107
+ const c = [C.button, C[a], n].filter(Boolean).join(" ");
108
+ return /* @__PURE__ */ e("button", { type: l, className: c, "data-variant": a, ...s, children: t });
18
109
  }
19
- const K = "_trigger_10bud_1", P = "_kbd_10bud_23", T = "_backdrop_10bud_31", q = "_dialog_10bud_42", S = "_input_10bud_53", D = "_list_10bud_69", i = {
20
- trigger: K,
21
- kbd: P,
22
- backdrop: T,
23
- dialog: q,
24
- input: S,
25
- list: D
110
+ const X = "_trigger_10bud_1", H = "_kbd_10bud_23", J = "_backdrop_10bud_31", M = "_dialog_10bud_42", W = "_input_10bud_53", Y = "_list_10bud_69", g = {
111
+ trigger: X,
112
+ kbd: H,
113
+ backdrop: J,
114
+ dialog: M,
115
+ input: W,
116
+ list: Y
26
117
  };
27
- function se({
28
- items: n,
29
- triggerLabel: s = "Search",
30
- placeholder: a = "Type a command or search…",
31
- label: o = "Command palette",
32
- className: t,
33
- ...u
118
+ function ke({
119
+ items: t,
120
+ triggerLabel: a = "Search",
121
+ placeholder: l = "Type a command or search…",
122
+ label: n = "Command palette",
123
+ className: s,
124
+ ...c
34
125
  }) {
35
- const [p, d] = f(!1), [h, w] = f(""), b = B(null);
36
- g(() => {
37
- p && b.current?.focus();
38
- }, [p]), g(() => {
39
- function l(c) {
40
- if ((c.metaKey || c.ctrlKey) && c.key.toLowerCase() === "k") {
41
- c.preventDefault(), d((C) => !C);
126
+ const [m, i] = k(!1), [u, b] = k(""), f = D(null);
127
+ B(() => {
128
+ m && f.current?.focus();
129
+ }, [m]), B(() => {
130
+ function o(_) {
131
+ if ((_.metaKey || _.ctrlKey) && _.key.toLowerCase() === "k") {
132
+ _.preventDefault(), i((N) => !N);
42
133
  return;
43
134
  }
44
- c.key === "Escape" && d(!1);
135
+ _.key === "Escape" && i(!1);
45
136
  }
46
- return document.addEventListener("keydown", l), () => document.removeEventListener("keydown", l);
137
+ return document.addEventListener("keydown", o), () => document.removeEventListener("keydown", o);
47
138
  }, []);
48
- const v = n.filter((l) => `${l.label} ${l.hint ?? ""}`.toLowerCase().includes(h.trim().toLowerCase())), j = [i.trigger, t].filter(Boolean).join(" ");
49
- return /* @__PURE__ */ r($, { children: [
50
- /* @__PURE__ */ r("button", { type: "button", className: j, onClick: () => d(!0), ...u, children: [
51
- /* @__PURE__ */ e("span", { children: s }),
52
- /* @__PURE__ */ e("kbd", { className: i.kbd, children: "⌘K" })
139
+ const h = t.filter((o) => `${o.label} ${o.hint ?? ""}`.toLowerCase().includes(u.trim().toLowerCase())), v = [g.trigger, s].filter(Boolean).join(" ");
140
+ return /* @__PURE__ */ r(E, { children: [
141
+ /* @__PURE__ */ r("button", { type: "button", className: v, onClick: () => i(!0), ...c, children: [
142
+ /* @__PURE__ */ e("span", { children: a }),
143
+ /* @__PURE__ */ e("kbd", { className: g.kbd, children: "⌘K" })
53
144
  ] }),
54
- p && /* @__PURE__ */ e("div", { className: i.backdrop, onClick: (l) => l.target === l.currentTarget && d(!1), children: /* @__PURE__ */ r("div", { className: i.dialog, role: "dialog", "aria-modal": "true", "aria-label": o, children: [
145
+ m && /* @__PURE__ */ e("div", { className: g.backdrop, onClick: (o) => o.target === o.currentTarget && i(!1), children: /* @__PURE__ */ r("div", { className: g.dialog, role: "dialog", "aria-modal": "true", "aria-label": n, children: [
55
146
  /* @__PURE__ */ e(
56
147
  "input",
57
148
  {
58
- ref: b,
149
+ ref: f,
59
150
  type: "text",
60
- className: i.input,
61
- placeholder: a,
62
- value: h,
63
- onChange: (l) => w(l.target.value),
151
+ className: g.input,
152
+ placeholder: l,
153
+ value: u,
154
+ onChange: (o) => b(o.target.value),
64
155
  autoComplete: "off"
65
156
  }
66
157
  ),
67
- /* @__PURE__ */ e("ul", { className: i.list, children: v.map((l) => (
158
+ /* @__PURE__ */ e("ul", { className: g.list, children: h.map((o) => (
68
159
  // Keyed by href, not label: two items can share a label (e.g.
69
160
  // a nav link and a more specific shortcut to the same topic).
70
- /* @__PURE__ */ e("li", { children: /* @__PURE__ */ r("a", { href: l.href, onClick: () => d(!1), children: [
71
- /* @__PURE__ */ e("span", { children: l.label }),
72
- l.hint && /* @__PURE__ */ e("small", { children: l.hint })
73
- ] }) }, l.href)
161
+ /* @__PURE__ */ e("li", { children: /* @__PURE__ */ r("a", { href: o.href, onClick: () => i(!1), children: [
162
+ /* @__PURE__ */ e("span", { children: o.label }),
163
+ o.hint && /* @__PURE__ */ e("small", { children: o.hint })
164
+ ] }) }, o.href)
74
165
  )) })
75
166
  ] }) })
76
167
  ] });
77
168
  }
78
- const R = "_eyebrow_1a4gy_1", F = {
79
- eyebrow: R
169
+ const z = "_eyebrow_1a4gy_1", ee = {
170
+ eyebrow: z
171
+ };
172
+ function ve({ children: t, className: a, ...l }) {
173
+ const n = [ee.eyebrow, a].filter(Boolean).join(" ");
174
+ return /* @__PURE__ */ e("p", { className: n, ...l, children: t });
175
+ }
176
+ const te = "_loadingLabel_1yug9_1", se = "_cursor_1yug9_10", $ = {
177
+ loadingLabel: te,
178
+ cursor: se
80
179
  };
81
- function le({ children: n, className: s, ...a }) {
82
- const o = [F.eyebrow, s].filter(Boolean).join(" ");
83
- return /* @__PURE__ */ e("p", { className: o, ...a, children: n });
180
+ function Ne({
181
+ isLoading: t,
182
+ loadingText: a,
183
+ children: l,
184
+ className: n,
185
+ style: s,
186
+ disabled: c,
187
+ type: m = "button",
188
+ ...i
189
+ }) {
190
+ const u = [n].filter(Boolean).join(" ");
191
+ return /* @__PURE__ */ e(
192
+ "button",
193
+ {
194
+ type: m,
195
+ className: u,
196
+ style: { ...s, ...t ? {
197
+ background: "var(--ds-color-bg)",
198
+ border: "1px solid var(--ds-color-accent)",
199
+ color: "var(--ds-color-accent)",
200
+ opacity: 1
201
+ } : void 0 },
202
+ disabled: !!c || t,
203
+ "aria-busy": t || void 0,
204
+ ...i,
205
+ children: t ? /* @__PURE__ */ r("span", { className: $.loadingLabel, children: [
206
+ /* @__PURE__ */ e("span", { "aria-hidden": "true", children: "$" }),
207
+ a,
208
+ /* @__PURE__ */ e("span", { "aria-hidden": "true", className: $.cursor })
209
+ ] }) : l
210
+ }
211
+ );
84
212
  }
85
- const G = "_panel_m16j3_1", O = {
86
- panel: G
213
+ const ae = "_panel_m16j3_1", le = {
214
+ panel: ae
87
215
  };
88
- function ne({ children: n, dots: s = !1, className: a, ...o }) {
89
- const t = [O.panel, s && "ds-dot-grid", a].filter(Boolean).join(" ");
90
- return /* @__PURE__ */ e("div", { className: t, ...o, children: n });
216
+ function we({ children: t, dots: a = !1, className: l, ...n }) {
217
+ const s = [le.panel, a && "ds-dot-grid", l].filter(Boolean).join(" ");
218
+ return /* @__PURE__ */ e("div", { className: s, ...n, children: t });
91
219
  }
92
- const Q = "_list_27va3_1", z = "_step_27va3_12", k = {
93
- list: Q,
94
- step: z
220
+ const ne = "_list_27va3_1", oe = "_step_27va3_12", j = {
221
+ list: ne,
222
+ step: oe
95
223
  };
96
- function ae({ steps: n, className: s, ...a }) {
97
- const o = [k.list, s].filter(Boolean).join(" ");
98
- return /* @__PURE__ */ e("ul", { className: o, ...a, children: n.map((t) => /* @__PURE__ */ r("li", { className: k.step, children: [
99
- t.label,
224
+ function Be({ steps: t, className: a, ...l }) {
225
+ const n = [j.list, a].filter(Boolean).join(" ");
226
+ return /* @__PURE__ */ e("ul", { className: n, ...l, children: t.map((s) => /* @__PURE__ */ r("li", { className: j.step, children: [
227
+ s.label,
100
228
  " ",
101
- /* @__PURE__ */ e("b", { children: t.value })
102
- ] }, t.label)) });
229
+ /* @__PURE__ */ e("b", { children: s.value })
230
+ ] }, s.label)) });
103
231
  }
104
- const A = "_grid_94gwu_1", H = "_cell_94gwu_12", I = "_value_94gwu_19", J = "_label_94gwu_28", _ = {
105
- grid: A,
106
- cell: H,
107
- value: I,
108
- label: J
232
+ const re = "_grid_94gwu_1", ce = "_cell_94gwu_12", ie = "_value_94gwu_19", de = "_label_94gwu_28", y = {
233
+ grid: re,
234
+ cell: ce,
235
+ value: ie,
236
+ label: de
109
237
  };
110
- function oe({ stats: n, className: s, ...a }) {
111
- const o = [_.grid, s].filter(Boolean).join(" ");
112
- return /* @__PURE__ */ e("dl", { className: o, ...a, children: n.map((t) => /* @__PURE__ */ r("div", { className: _.cell, children: [
113
- /* @__PURE__ */ e("dd", { className: _.value, children: t.value }),
114
- /* @__PURE__ */ e("dt", { className: _.label, children: t.label })
115
- ] }, t.label)) });
238
+ function Ce({ stats: t, className: a, ...l }) {
239
+ const n = [y.grid, a].filter(Boolean).join(" ");
240
+ return /* @__PURE__ */ e("dl", { className: n, ...l, children: t.map((s) => /* @__PURE__ */ r("div", { className: y.cell, children: [
241
+ /* @__PURE__ */ e("dd", { className: y.value, children: s.value }),
242
+ /* @__PURE__ */ e("dt", { className: y.label, children: s.label })
243
+ ] }, s.label)) });
116
244
  }
117
- const M = "_list_17qxg_1", U = "_tag_17qxg_10", N = {
118
- list: M,
119
- tag: U
245
+ const ue = "_list_17qxg_1", _e = "_tag_17qxg_10", x = {
246
+ list: ue,
247
+ tag: _e
120
248
  };
121
- function re({ tags: n, className: s, ...a }) {
122
- const o = [N.list, s].filter(Boolean).join(" ");
123
- return /* @__PURE__ */ e("ul", { className: o, ...a, children: n.map((t) => /* @__PURE__ */ e("li", { className: N.tag, children: t }, t)) });
249
+ function $e({ tags: t, className: a, ...l }) {
250
+ const n = [x.list, a].filter(Boolean).join(" ");
251
+ return /* @__PURE__ */ e("ul", { className: n, ...l, children: t.map((s) => /* @__PURE__ */ e("li", { className: x.tag, children: s }, s)) });
124
252
  }
125
- const V = "_prompt_vxkw7_1", W = "_path_vxkw7_11", X = "_cursor_vxkw7_15", m = {
126
- prompt: V,
127
- path: W,
128
- cursor: X
253
+ const me = "_prompt_vxkw7_1", be = "_path_vxkw7_11", pe = "_cursor_vxkw7_15", w = {
254
+ prompt: me,
255
+ path: be,
256
+ cursor: pe
129
257
  };
130
- function ce({ user: n, host: s, command: a, className: o, ...t }) {
131
- const u = [m.prompt, o].filter(Boolean).join(" ");
132
- return /* @__PURE__ */ r("p", { className: u, ...t, children: [
133
- /* @__PURE__ */ r("span", { className: m.path, children: [
134
- n,
258
+ function je({ user: t, host: a, command: l, className: n, ...s }) {
259
+ const c = [w.prompt, n].filter(Boolean).join(" ");
260
+ return /* @__PURE__ */ r("p", { className: c, ...s, children: [
261
+ /* @__PURE__ */ r("span", { className: w.path, children: [
262
+ t,
135
263
  "@",
136
- s
264
+ a
137
265
  ] }),
138
266
  " ~$ ",
139
- a,
140
- /* @__PURE__ */ e("span", { className: m.cursor, "aria-hidden": "true" })
267
+ l,
268
+ /* @__PURE__ */ e("span", { className: w.cursor, "aria-hidden": "true" })
141
269
  ] });
142
270
  }
143
271
  export {
144
- te as Button,
145
- se as CommandPalette,
146
- le as Eyebrow,
147
- ne as Panel,
148
- ae as PipelineBadges,
149
- oe as StatGrid,
150
- re as TagList,
151
- ce as TerminalPrompt
272
+ he as Avatar,
273
+ ye as Button,
274
+ ke as CommandPalette,
275
+ ve as Eyebrow,
276
+ Ne as LoadingButton,
277
+ we as Panel,
278
+ Be as PipelineBadges,
279
+ Ce as StatGrid,
280
+ $e as TagList,
281
+ je as TerminalPrompt
152
282
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alishenriques/design-system",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Isolated design system for Alis portfolio and future products",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",