@oleksandr-94/aura-css 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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +593 -0
  3. package/dist/aura-flat.css +1611 -0
  4. package/dist/aura-flat.min.css +1 -0
  5. package/dist/aura-neu.css +1622 -0
  6. package/dist/aura-neu.min.css +1 -0
  7. package/dist/aura.css +1634 -0
  8. package/dist/aura.min.css +1 -0
  9. package/dist/interactions.d.ts +57 -0
  10. package/dist/interactions.global.min.js +1 -0
  11. package/dist/interactions.min.mjs +1 -0
  12. package/dist/interactions.mjs +208 -0
  13. package/package.json +72 -0
  14. package/src/_config.scss +72 -0
  15. package/src/_functions.scss +23 -0
  16. package/src/_layers.scss +4 -0
  17. package/src/_surface.scss +49 -0
  18. package/src/_tokens.scss +65 -0
  19. package/src/base/_a11y.scss +31 -0
  20. package/src/base/_reset.scss +7 -0
  21. package/src/components/_accordion.scss +62 -0
  22. package/src/components/_alert.scss +43 -0
  23. package/src/components/_avatar.scss +50 -0
  24. package/src/components/_badge.scss +61 -0
  25. package/src/components/_button.scss +79 -0
  26. package/src/components/_card.scss +58 -0
  27. package/src/components/_checkbox.scss +51 -0
  28. package/src/components/_dropdown.scss +73 -0
  29. package/src/components/_file.scss +42 -0
  30. package/src/components/_group.scss +51 -0
  31. package/src/components/_input.scss +85 -0
  32. package/src/components/_modal.scss +43 -0
  33. package/src/components/_pagination.scss +87 -0
  34. package/src/components/_progress.scss +44 -0
  35. package/src/components/_radio.scss +42 -0
  36. package/src/components/_range.scss +27 -0
  37. package/src/components/_rating.scss +43 -0
  38. package/src/components/_segmented.scss +60 -0
  39. package/src/components/_switch.scss +79 -0
  40. package/src/components/_table.scss +38 -0
  41. package/src/components/_tabs.scss +150 -0
  42. package/src/components/_toast.scss +59 -0
  43. package/src/components/_tooltip.scss +60 -0
  44. package/src/index.scss +32 -0
  45. package/src/js/global.js +7 -0
  46. package/src/js/interactions.auto.js +5 -0
  47. package/src/js/interactions.js +192 -0
  48. package/src/skins/_flat.scss +29 -0
  49. package/src/skins/_glass.scss +40 -0
  50. package/src/skins/_neu.scss +49 -0
@@ -0,0 +1 @@
1
+ @layer base, components, a11y;:root{--radius-sm: 6px;--radius-md: 8px;--radius-lg: 12px;--radius-pill: 999px;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-6: 24px;--space-8: 32px;--font: "Plus Jakarta Sans", system-ui, sans-serif;--fs-xs: 12px;--fs-sm: 13px;--fs-md: 14px;--fs-lg: 16px;--fs-xl: 20px;--blur: 20px;--gradient: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);--gradient-tint: #ffd23f;--z-dropdown: 1000;--z-sticky: 1020;--z-modal: 1050;--z-toast: 1080}:root,[data-theme=aura-dark]{--primary: #00BD7D;--on-primary: #0f1a14;--primary-container: color-mix(in srgb, #00BD7D 16%, transparent);--on-primary-container: #00BD7D;--secondary: #3B82F6;--on-secondary: #ffffff;--secondary-container: color-mix(in srgb, #3B82F6 16%, transparent);--on-secondary-container: #3B82F6;--accent: #12E0C0;--on-accent: #0f1a14;--accent-container: color-mix(in srgb, #12E0C0 16%, transparent);--on-accent-container: #12E0C0;--success: #16A34A;--on-success: #ffffff;--success-container: color-mix(in srgb, #16A34A 16%, transparent);--on-success-container: #16A34A;--warning: #E0913A;--on-warning: #0f1a14;--warning-container: color-mix(in srgb, #E0913A 16%, transparent);--on-warning-container: #E0913A;--error: #EA4B5E;--on-error: #ffffff;--error-container: color-mix(in srgb, #EA4B5E 16%, transparent);--on-error-container: #EA4B5E;--info: #3B82F6;--on-info: #ffffff;--info-container: color-mix(in srgb, #3B82F6 16%, transparent);--on-info-container: #3B82F6;--surface: #0e1526;--surface-1: #141d33;--surface-2: #1b2540;--on-surface: #e7ecf5;--on-surface-muted: rgba(231, 236, 245, 0.62);--outline: rgba(255, 255, 255, 0.14);--outline-strong: rgba(255, 255, 255, 0.24);--glass-film: rgba(255, 255, 255, 0.06);--glass-film-2: rgba(255, 255, 255, 0.1);--tip-bg: rgba(238, 244, 250, 0.96);--tip-text: #0e1526;--shadow-1: 0 8px 32px rgba(0, 0, 0, 0.4);--shadow-2: 0 16px 44px rgba(0, 0, 0, 0.5)}[data-theme=aura-light]{--primary: #00A86B;--on-primary: #ffffff;--primary-container: color-mix(in srgb, #00A86B 16%, transparent);--on-primary-container: #00A86B;--secondary: #2563EB;--on-secondary: #ffffff;--secondary-container: color-mix(in srgb, #2563EB 16%, transparent);--on-secondary-container: #2563EB;--accent: #0FB89B;--on-accent: #0f1a14;--accent-container: color-mix(in srgb, #0FB89B 16%, transparent);--on-accent-container: #0FB89B;--success: #16A34A;--on-success: #ffffff;--success-container: color-mix(in srgb, #16A34A 16%, transparent);--on-success-container: #16A34A;--warning: #D97706;--on-warning: #ffffff;--warning-container: color-mix(in srgb, #D97706 16%, transparent);--on-warning-container: #D97706;--error: #DC2626;--on-error: #ffffff;--error-container: color-mix(in srgb, #DC2626 16%, transparent);--on-error-container: #DC2626;--info: #2563EB;--on-info: #ffffff;--info-container: color-mix(in srgb, #2563EB 16%, transparent);--on-info-container: #2563EB;--surface: #eef3f2;--surface-1: #ffffff;--surface-2: #f5faf8;--on-surface: #10231b;--on-surface-muted: rgba(16, 35, 27, 0.62);--outline: rgba(12, 70, 50, 0.16);--outline-strong: rgba(12, 70, 50, 0.3);--glass-film: rgba(255, 255, 255, 0.55);--glass-film-2: rgba(255, 255, 255, 0.7);--tip-bg: rgba(16, 24, 40, 0.95);--tip-text: #eef4fa;--shadow-1: 0 10px 30px rgba(10, 90, 60, 0.14);--shadow-2: 0 16px 40px rgba(10, 90, 60, 0.18)}@layer base{*,*::before,*::after{box-sizing:border-box}}@layer a11y{@media(prefers-reduced-motion: reduce){*,*::before,*::after{animation-duration:1ms;animation-iteration-count:1;transition-duration:1ms;scroll-behavior:auto}}.sr-only{position:absolute !important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}}@layer components{.btn{--_c: var(--primary);--_bg: var(--_c);--_fg: var(--on-primary);display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);font:inherit;font-weight:700;font-size:var(--fs-md);line-height:1;padding:10px 18px;border-radius:var(--radius-md);cursor:pointer;transition:filter .15s ease,transform .05s ease,box-shadow .15s ease;background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28)}.btn:hover{filter:brightness(1.06)}.btn:active{transform:translateY(1px)}.btn:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.btn:disabled,.btn.btn--disabled{opacity:.5;cursor:not-allowed;filter:none}.btn.btn--secondary{--_c: var(--secondary);--_fg: var(--on-secondary)}.btn.btn--accent{--_c: var(--accent);--_fg: var(--on-accent)}.btn.btn--success{--_c: var(--success);--_fg: var(--on-success)}.btn.btn--warning{--_c: var(--warning);--_fg: var(--on-warning)}.btn.btn--error{--_c: var(--error);--_fg: var(--on-error)}.btn.btn--info{--_c: var(--info);--_fg: var(--on-info)}.btn.btn--gradient{--_bg: linear-gradient(135deg, color-mix(in srgb, var(--_c) 62%, var(--gradient-tint)) 0%, var(--_c) 48%, color-mix(in srgb, var(--_c) 84%, #000) 100%);--_shadow-color: var(--_c)}.btn.btn--ghost{background:rgba(0,0,0,0);color:var(--on-surface);border:1px solid var(--outline-strong);box-shadow:none}.btn.btn--ghost:hover{background:color-mix(in srgb, var(--on-surface) 8%, transparent);filter:none}.btn.btn--ghost:active{box-shadow:none;transform:translateY(1px)}.btn.btn--outline{background:rgba(0,0,0,0);color:var(--_c);border:1px solid var(--_c);box-shadow:none}.btn.btn--outline:hover{background:color-mix(in srgb, var(--_c) 12%, transparent);filter:none}.btn.btn--outline:active{box-shadow:none;transform:translateY(1px)}.btn.btn--sm{padding:7px 12px;font-size:var(--fs-sm);border-radius:var(--radius-sm)}.btn.btn--lg{padding:13px 22px;font-size:var(--fs-lg)}.btn.btn--block{display:flex;width:100%}}@layer components{.card{--_c: var(--primary);background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur)) saturate(180%);backdrop-filter:blur(var(--blur)) saturate(180%);border:1px solid var(--outline);box-shadow:var(--shadow-1),inset 0 1px 0 hsla(0,0%,100%,.12);border-radius:var(--radius-lg);padding:var(--space-6);color:var(--on-surface);display:flex;flex-direction:column;gap:var(--space-4)}.card__header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}.card__title{margin:0;font-size:var(--fs-xl);font-weight:800}.card__body{margin:0;color:var(--on-surface-muted);font-size:var(--fs-md);line-height:1.5}.card__actions{display:flex;gap:var(--space-2);margin-top:auto}.card--primary{--_c: var(--primary)}.card--success{--_c: var(--success)}.card--warning{--_c: var(--warning)}.card--error{--_c: var(--error)}.card--info{--_c: var(--info)}.card--primary,.card--success,.card--warning,.card--error,.card--info{border-inline-start:3px solid var(--_c)}.card--gradient{background:linear-gradient(135deg, color-mix(in srgb, var(--_c) 62%, var(--gradient-tint)) 0%, var(--_c) 48%, color-mix(in srgb, var(--_c) 84%, #000) 100%);border:none;color:#fff}.card--gradient .card__body{color:hsla(0,0%,100%,.82)}}@layer components{.field{display:flex;flex-direction:column;gap:var(--space-2)}.field__label{font-size:var(--fs-xs);font-weight:600;color:var(--on-surface)}.field__label--required::after{content:" *";color:var(--error)}.field__hint{font-size:var(--fs-xs);color:var(--on-surface-muted)}.field__hint--error{color:var(--error)}.field__hint--success{color:var(--success)}.input,.select,.textarea{background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong);font:inherit;font-size:var(--fs-md);color:var(--on-surface);width:100%;padding:10px 14px;border-radius:var(--radius-md);transition:border-color .15s ease}.input::placeholder,.select::placeholder,.textarea::placeholder{color:var(--on-surface-muted)}.input:focus-visible,.select:focus-visible,.textarea:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.input:disabled,.select:disabled,.textarea:disabled{opacity:.5;cursor:not-allowed}.textarea{min-height:84px;resize:vertical}.select{appearance:none;-webkit-appearance:none;padding-inline-end:34px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5l3.5 3.5 3.5-3.5' fill='none' stroke='%238b93a1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center}.input--error,.select--error,.textarea--error{border-color:var(--error)}.input--error:focus-visible,.select--error:focus-visible,.textarea--error:focus-visible{outline-color:var(--error)}.input--success,.select--success,.textarea--success{border-color:var(--success)}.input--success:focus-visible,.select--success:focus-visible,.textarea--success:focus-visible{outline-color:var(--success)}.input--sm,.select--sm,.textarea--sm{padding-block:7px;padding-inline:11px;font-size:var(--fs-sm);border-radius:var(--radius-sm)}.input--lg,.select--lg,.textarea--lg{padding-block:13px;padding-inline:16px;font-size:var(--fs-lg)}.select--sm,.select--lg{padding-inline-end:34px}}@layer components{.badge{--_bg: color-mix(in srgb, var(--on-surface) 10%, transparent);--_fg: var(--on-surface);display:inline-flex;align-items:center;gap:6px;padding:3px 10px;font-size:var(--fs-xs);font-weight:700;line-height:1.5;white-space:nowrap;border-radius:var(--radius-pill);border:1px solid rgba(0,0,0,0);background:var(--_bg);color:var(--_fg);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.22)}.badge.badge--primary{--_bg: var(--primary-container);--_fg: var(--on-primary-container)}.badge.badge--secondary{--_bg: var(--secondary-container);--_fg: var(--on-secondary-container)}.badge.badge--accent{--_bg: var(--accent-container);--_fg: var(--on-accent-container)}.badge.badge--success{--_bg: var(--success-container);--_fg: var(--on-success-container)}.badge.badge--warning{--_bg: var(--warning-container);--_fg: var(--on-warning-container)}.badge.badge--error{--_bg: var(--error-container);--_fg: var(--on-error-container)}.badge.badge--info{--_bg: var(--info-container);--_fg: var(--on-info-container)}.badge.badge--outline{background:rgba(0,0,0,0);border-color:color-mix(in srgb, var(--_fg) 45%, transparent);box-shadow:none}.badge.badge--sm{padding:2px 8px;font-size:11px}.badge.badge--lg{padding:5px 13px;font-size:var(--fs-sm)}.badge__dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}}@layer components{.alert{--_c: var(--primary);display:flex;align-items:flex-start;gap:12px;padding:14px 16px;border-radius:var(--radius-md);background:color-mix(in srgb, var(--_c) 13%, var(--surface-1));color:var(--on-surface);border:1px solid var(--outline);border-left:3px solid var(--_c);font-size:var(--fs-md);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.22)}.alert.alert--success{--_c: var(--success)}.alert.alert--warning{--_c: var(--warning)}.alert.alert--error{--_c: var(--error)}.alert.alert--info{--_c: var(--info)}.alert__icon{color:var(--_c);font-size:18px;line-height:1.35;flex:none}.alert__title{font-weight:700}.alert__body{color:var(--on-surface-muted);font-size:var(--fs-sm);margin-top:2px}}@layer components{.switch{--_c: var(--primary);position:relative;display:inline-flex;flex:none;width:46px;height:26px;vertical-align:middle;cursor:pointer}.switch input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer}.switch__track{position:absolute;inset:0;border-radius:var(--radius-pill);transition:background .2s ease,border-color .2s ease,box-shadow .2s ease;background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong)}.switch__thumb{position:absolute;top:4px;left:4px;width:18px;height:18px;border-radius:50%;background:var(--on-surface-muted);transition:transform .2s ease,background .2s ease}.switch input:checked~.switch__track{--_bg: var(--_c);--_fg: #fff;background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28)}.switch input:checked~.switch__thumb{transform:translateX(20px);background:#fff}.switch input:focus-visible~.switch__track{outline:2px solid var(--_c);outline-offset:2px}.switch input:disabled~.switch__track,.switch input:disabled~.switch__thumb{opacity:.5}.switch--success{--_c: var(--success)}.switch--warning{--_c: var(--warning)}.switch--error{--_c: var(--error)}.switch--sm{width:38px;height:22px}.switch--sm .switch__thumb{width:14px;height:14px}.switch--sm input:checked~.switch__thumb{transform:translateX(16px)}.switch--lg{width:56px;height:32px}.switch--lg .switch__thumb{width:24px;height:24px}.switch--lg input:checked~.switch__thumb{transform:translateX(24px)}}@layer components{.checkbox{--_c: var(--primary);appearance:none;-webkit-appearance:none;margin:0;flex:none;width:18px;height:18px;border-radius:var(--radius-sm);cursor:pointer;position:relative;vertical-align:middle;transition:background .15s ease,border-color .15s ease;background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong)}.checkbox:checked,.checkbox:indeterminate{--_bg: var(--_c);--_fg: #fff;background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28)}.checkbox:checked::after{content:"";position:absolute;left:50%;top:50%;width:5px;height:9px;border:solid #fff;border-width:0 2px 2px 0;transform:translate(-50%, -58%) rotate(45deg)}.checkbox:indeterminate::after{content:"";position:absolute;left:3px;right:3px;top:calc(50% - 1px);height:2px;background:#fff;border-radius:1px}.checkbox:focus-visible{outline:2px solid var(--_c);outline-offset:2px}.checkbox:disabled{opacity:.5;cursor:not-allowed}.checkbox.checkbox--success{--_c: var(--success)}.checkbox.checkbox--warning{--_c: var(--warning)}.checkbox.checkbox--error{--_c: var(--error)}}@layer components{.radio{--_c: var(--primary);appearance:none;-webkit-appearance:none;margin:0;flex:none;width:18px;height:18px;border-radius:50%;cursor:pointer;position:relative;vertical-align:middle;transition:background .15s ease,border-color .15s ease;background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong)}.radio:checked{--_bg: var(--_c);--_fg: #fff;background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28)}.radio:checked::after{content:"";position:absolute;inset:4px;border-radius:50%;background:#fff}.radio:focus-visible{outline:2px solid var(--_c);outline-offset:2px}.radio:disabled{opacity:.5;cursor:not-allowed}.radio.radio--success{--_c: var(--success)}.radio.radio--warning{--_c: var(--warning)}.radio.radio--error{--_c: var(--error)}}@layer components{.range{--_c: var(--primary);width:100%;height:22px;accent-color:var(--_c);cursor:pointer}.range:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.range:disabled{opacity:.5;cursor:not-allowed}.range.range--success{--_c: var(--success)}.range.range--warning{--_c: var(--warning)}.range.range--error{--_c: var(--error)}.range.range--sm{height:16px}.range.range--lg{height:28px}}@layer components{.file{--_c: var(--primary);max-width:100%;font:inherit;font-size:var(--fs-sm);color:var(--on-surface-muted);cursor:pointer}.file::file-selector-button{font:inherit;font-weight:700;font-size:var(--fs-sm);margin-inline-end:12px;padding:8px 14px;border:none;border-radius:var(--radius-md);background:var(--_c);color:var(--on-primary);cursor:pointer;transition:filter .15s ease}.file::file-selector-button:hover{filter:brightness(1.06)}.file:focus-visible{outline:2px solid var(--primary);outline-offset:2px;border-radius:var(--radius-md)}.file:disabled{opacity:.5;cursor:not-allowed}.file.file--ghost::file-selector-button{background:rgba(0,0,0,0);color:var(--on-surface);border:1px solid var(--outline-strong)}}@layer components{.rating{--_c: var(--warning);display:inline-flex;flex-direction:row-reverse;justify-content:flex-end;gap:2px}.rating input{position:absolute;width:1px;height:1px;opacity:0;margin:0}.rating label{font-size:24px;line-height:1;color:var(--outline-strong);cursor:pointer;transition:color .12s ease,transform .12s ease}.rating label:hover{transform:scale(1.1)}.rating input:checked~label,.rating label:hover,.rating label:hover~label{color:var(--_c)}.rating input:focus-visible+label{outline:2px solid var(--primary);outline-offset:2px;border-radius:4px}.rating.rating--sm label{font-size:18px}.rating.rating--lg label{font-size:32px}}@layer components{.tabs{display:inline-flex;gap:4px;padding:4px;border-radius:var(--radius-md);background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong)}.tabs--block{display:flex;width:100%}.tabs--block .tab{flex:1}.tab{font:inherit;font-weight:700;font-size:var(--fs-sm);padding:8px 14px;border:none;border-radius:var(--radius-sm);background:rgba(0,0,0,0);color:var(--on-surface-muted);cursor:pointer;white-space:nowrap;transition:color .15s ease}.tab:hover:not(.tab--active){color:var(--on-surface)}.tab:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.tab--active{--_bg: var(--primary);--_fg: var(--on-primary);background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28);color:var(--_fg)}.tab-panel{margin-top:var(--space-4)}.tabs--underline{gap:4px;padding:0;background:none;border:none;border-bottom:1px solid var(--outline);border-radius:0;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.tabs--underline .tab{border-radius:0;padding:10px 14px;border-bottom:2px solid rgba(0,0,0,0);margin-bottom:-1px}.tabs--underline .tab--active{background:none;box-shadow:none;color:var(--primary);border-bottom-color:var(--primary)}.tabs--lift{gap:4px;padding:0;background:none;border:none;border-radius:0;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.tabs--lift .tab{position:relative;z-index:0;border-radius:var(--radius-md) var(--radius-md) 0 0;padding:10px 16px;border:1px solid rgba(0,0,0,0);border-bottom:none;margin-bottom:-1px}.tabs--lift .tab--active{z-index:1;background:var(--surface-1);box-shadow:none;color:var(--on-surface);border-color:var(--outline)}.tab-panels{padding-top:var(--space-4)}.tab-panels .tab-panel{margin-top:0}.tabs--lift+.tab-panels{padding:var(--space-6);background:var(--surface-1);border:1px solid var(--outline);border-radius:0 0 var(--radius-lg) var(--radius-lg)}.tab-card{background:var(--surface-1);border:1px solid var(--outline);border-radius:var(--radius-lg);overflow:hidden}.tab-card>.tabs{display:flex;background:none;border:none;border-bottom:1px solid var(--outline);border-radius:0;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;padding:var(--space-2)}.tab-card>.tabs--underline{padding:var(--space-1) var(--space-2) 0}.tab-card>.tab-panels{margin-top:0;padding:var(--space-6)}.tabs--sm .tab{padding:5px 10px;font-size:var(--fs-xs)}.tabs--lg .tab{padding:11px 18px;font-size:var(--fs-md)}}@layer components{.table{width:100%;border-collapse:collapse;font-size:var(--fs-md);color:var(--on-surface)}.table th,.table td{text-align:left;padding:11px 14px;border-bottom:1px solid var(--outline)}.table th{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:var(--on-surface-muted)}.table tbody tr:last-child td{border-bottom:none}.table tbody tr:hover{background:color-mix(in srgb, var(--on-surface) 5%, transparent)}.table--zebra tbody tr:nth-child(even){background:color-mix(in srgb, var(--on-surface) 4%, transparent)}.table--compact th,.table--compact td{padding:7px 10px}}@layer components{.group,.btn-group{display:inline-flex;align-items:stretch;border-radius:var(--radius-md)}.group>*,.btn-group>*{position:relative;border-radius:0;box-shadow:none}.group>:not(:first-child),.btn-group>:not(:first-child){margin-inline-start:-1px}.group>:hover,.group>:focus-visible,.group>:focus-within,.btn-group>:hover,.btn-group>:focus-visible,.btn-group>:focus-within{z-index:1}.group>:first-child,.btn-group>:first-child{border-start-start-radius:var(--radius-md);border-end-start-radius:var(--radius-md)}.group>:last-child,.btn-group>:last-child{border-start-end-radius:var(--radius-md);border-end-end-radius:var(--radius-md)}.group>.input,.group>.select,.btn-group>.input,.btn-group>.select{flex:1;width:auto;min-width:0}.group--block,.btn-group--block{display:flex;width:100%}.group--block>*,.btn-group--block>*{flex:1}}@layer components{.segmented{display:inline-flex;gap:4px;padding:4px;border-radius:var(--radius-md);background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong)}.segmented--block{display:flex;width:100%}.segmented--block .segmented__option{flex:1}.segmented__option{position:relative;display:inline-flex;flex:none}.segmented__option input{position:absolute;inset:0;width:100%;margin:0;opacity:0;cursor:pointer}.segmented__option span{flex:1;text-align:center;padding:8px 14px;border-radius:var(--radius-sm);font-weight:700;font-size:var(--fs-sm);color:var(--on-surface-muted);white-space:nowrap;-webkit-user-select:none;user-select:none;transition:color .15s ease}.segmented__option input:checked+span{--_c: var(--primary);--_bg: var(--_c);--_fg: var(--on-primary);background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28);color:var(--_fg)}.segmented__option input:focus-visible+span{outline:2px solid var(--primary);outline-offset:2px}}@layer components{.progress{--_c: var(--primary);display:block;width:100%;height:8px;border-radius:var(--radius-pill);overflow:hidden;background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur));backdrop-filter:blur(var(--blur));border:1px solid var(--outline-strong)}.progress__bar{display:block;height:100%;border-radius:inherit;background:var(--_c);transition:width .3s ease}.progress--success{--_c: var(--success)}.progress--warning{--_c: var(--warning)}.progress--error{--_c: var(--error)}.spinner{display:inline-block;width:28px;height:28px;border:3px solid var(--outline-strong);border-top-color:var(--primary);border-radius:50%;animation:spin .8s linear infinite}.spinner--sm{width:18px;height:18px;border-width:2px}.spinner--lg{width:40px;height:40px;border-width:4px}@keyframes spin{to{transform:rotate(360deg)}}}@layer components{.tooltip{position:relative;display:inline-flex}.tooltip__text{visibility:hidden;opacity:0;position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);white-space:nowrap;background:var(--tip-bg);color:var(--tip-text);font-size:var(--fs-xs);font-weight:600;padding:6px 10px;border-radius:var(--radius-sm);box-shadow:0 6px 20px rgba(0,0,0,.25);z-index:var(--z-dropdown);transition:opacity .15s ease,visibility .15s ease}.tooltip__text::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid rgba(0,0,0,0);border-top-color:var(--tip-bg)}.tooltip:hover .tooltip__text,.tooltip:focus-within .tooltip__text{visibility:visible;opacity:1}.tooltip--bottom .tooltip__text{bottom:auto;top:calc(100% + 8px)}.tooltip--bottom .tooltip__text::after{top:auto;bottom:100%;border-top-color:rgba(0,0,0,0);border-bottom-color:var(--tip-bg)}}@layer components{.modal-overlay{position:fixed;inset:0;z-index:var(--z-modal);display:grid;place-items:center;padding:20px;background:rgba(4,10,20,.5);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease}.modal-overlay[data-state=open]{opacity:1;visibility:visible}.modal{width:100%;max-width:440px;padding:24px;border-radius:var(--radius-lg);background:var(--surface-1);border:1px solid var(--outline);box-shadow:var(--shadow-2);transform:translateY(10px) scale(0.98);transition:transform .2s ease}.modal-overlay[data-state=open] .modal{transform:none}.modal__title{margin:0 0 8px;font-size:var(--fs-xl);font-weight:800}.modal__body{margin:0 0 20px;color:var(--on-surface-muted);font-size:var(--fs-md);line-height:1.5}.modal__actions{display:flex;gap:10px;justify-content:flex-end}}@layer components{.dropdown{position:relative;display:inline-block}.dropdown__menu{position:absolute;top:calc(100% + 6px);left:0;z-index:var(--z-dropdown);min-width:180px;padding:6px;border-radius:var(--radius-md);background:var(--glass-film-2);-webkit-backdrop-filter:blur(var(--blur)) saturate(180%);backdrop-filter:blur(var(--blur)) saturate(180%);border:1px solid var(--outline);box-shadow:var(--shadow-2),inset 0 1px 0 hsla(0,0%,100%,.12);opacity:0;visibility:hidden;transform:translateY(-4px);transition:opacity .15s ease,transform .15s ease,visibility .15s ease}.dropdown__menu--end{left:auto;right:0}.dropdown[data-state=open] .dropdown__menu{opacity:1;visibility:visible;transform:none}.dropdown__item{display:block;width:100%;text-align:left;padding:9px 12px;border:none;border-radius:var(--radius-sm);background:none;color:var(--on-surface);font:inherit;font-size:var(--fs-sm);font-weight:600;text-decoration:none;cursor:pointer}.dropdown__item:hover{background:color-mix(in srgb, var(--on-surface) 8%, transparent)}.dropdown__divider{height:1px;margin:6px 4px;background:var(--outline)}.dropdown__caret{display:inline-block;width:8px;height:8px;margin-inline-start:6px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;border-bottom-right-radius:2px;transform:translateY(-2px) rotate(45deg);transition:transform .2s ease}.dropdown[data-state=open] .dropdown__caret{transform:translateY(1px) rotate(-135deg)}}@layer components{.avatar{position:relative;display:inline-grid;place-items:center;width:40px;height:40px;flex:none;border-radius:50%;overflow:hidden;font-weight:700;font-size:var(--fs-md);color:var(--on-surface);background:color-mix(in srgb, var(--primary) 22%, var(--surface-2));border:2px solid var(--surface-1)}.avatar img{width:100%;height:100%;object-fit:cover;border-radius:inherit}.avatar--sm{width:30px;height:30px;font-size:var(--fs-xs)}.avatar--lg{width:56px;height:56px;font-size:var(--fs-xl)}.avatar--square{border-radius:var(--radius-md)}.avatar__status{position:absolute;right:0;bottom:0;width:11px;height:11px;border-radius:50%;background:var(--on-surface-muted);border:2px solid var(--surface-1)}.avatar__status--online{background:var(--success)}.avatar__status--busy{background:var(--error)}.avatar-group{display:inline-flex}.avatar-group .avatar:not(:first-child){margin-left:-12px}}@layer components{.accordion{display:flex;flex-direction:column;gap:8px}.accordion__item{border-radius:var(--radius-md);overflow:hidden;background:var(--glass-film);-webkit-backdrop-filter:blur(var(--blur)) saturate(180%);backdrop-filter:blur(var(--blur)) saturate(180%);border:1px solid var(--outline);box-shadow:var(--shadow-1),inset 0 1px 0 hsla(0,0%,100%,.12)}.accordion__head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;font-weight:700;font-size:var(--fs-md);cursor:pointer;list-style:none;-webkit-user-select:none;user-select:none}.accordion__head::-webkit-details-marker{display:none}.accordion__head::after{content:"";flex:none;width:9px;height:9px;margin-inline-start:8px;border-right:2px solid var(--on-surface-muted);border-bottom:2px solid var(--on-surface-muted);border-bottom-right-radius:2px;transform:translateY(-2px) rotate(45deg);transition:transform .2s ease}.accordion__head:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.accordion__item[open]>.accordion__head::after{transform:translateY(2px) rotate(-135deg)}.accordion__body{padding:0 16px 16px;color:var(--on-surface-muted);font-size:var(--fs-sm);line-height:1.5}}@layer components{.toast-container{position:fixed;top:20px;right:20px;z-index:var(--z-toast);display:flex;flex-direction:column;gap:10px;width:min(360px,100vw - 40px);pointer-events:none}.toast-container--bottom{top:auto;bottom:20px}.toast{--_c: var(--primary);pointer-events:auto;display:flex;align-items:flex-start;gap:12px;padding:12px 14px;border-radius:var(--radius-md);background:var(--surface-1);border:1px solid var(--outline);border-left:3px solid var(--_c);box-shadow:var(--shadow-2);font-size:var(--fs-sm);opacity:0;transform:translateX(12px);transition:opacity .2s ease,transform .2s ease}.toast[data-state=open]{opacity:1;transform:none}.toast--success{--_c: var(--success)}.toast--warning{--_c: var(--warning)}.toast--error{--_c: var(--error)}.toast--info{--_c: var(--info)}.toast__body{flex:1;color:var(--on-surface);line-height:1.4}.toast__close{flex:none;border:none;background:none;color:var(--on-surface-muted);font-size:18px;line-height:1;cursor:pointer;padding:0 2px}.toast__close:hover{color:var(--on-surface)}}@layer components{.pagination{display:inline-flex;gap:4px}.pagination__item{min-width:36px;height:36px;padding:0 8px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-md);border:1px solid var(--outline);background:var(--surface-1);color:var(--on-surface);font:inherit;font-size:var(--fs-sm);font-weight:600;text-decoration:none;cursor:pointer}.pagination__item:hover:not(.pagination__item--active):not(:disabled):not(.pagination__item--disabled){background:color-mix(in srgb, var(--on-surface) 8%, transparent)}.pagination__item:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.pagination__item:disabled,.pagination__item.pagination__item--disabled{opacity:.5;cursor:not-allowed}.pagination__item--active{--_bg: var(--primary);--_fg: var(--on-primary);background:var(--_bg);color:var(--_fg);border:1px solid rgba(0,0,0,0);box-shadow:0 6px 18px color-mix(in srgb, var(--_shadow-color, var(--_bg)) 40%, transparent),inset 0 1px 0 hsla(0,0%,100%,.28);border-color:rgba(0,0,0,0)}.pagination--joined{gap:0}.pagination--joined .pagination__item{position:relative;border-radius:0}.pagination--joined .pagination__item:not(:first-child){margin-inline-start:-1px}.pagination--joined .pagination__item:hover:not(:disabled):not(.pagination__item--disabled),.pagination--joined .pagination__item:focus-visible,.pagination--joined .pagination__item--active{z-index:1}.pagination--joined .pagination__item:first-child{border-start-start-radius:var(--radius-md);border-end-start-radius:var(--radius-md)}.pagination--joined .pagination__item:last-child{border-start-end-radius:var(--radius-md);border-end-end-radius:var(--radius-md)}.pagination--sm .pagination__item{min-width:30px;height:30px;font-size:var(--fs-xs)}.pagination__ellipsis{min-width:24px;height:36px;display:inline-flex;align-items:flex-end;justify-content:center;padding-bottom:6px;color:var(--on-surface-muted);-webkit-user-select:none;user-select:none}.pagination--sm .pagination__ellipsis{height:30px}}
@@ -0,0 +1,57 @@
1
+ // Type definitions for Aura's optional behaviour layer.
2
+ // Hand-maintained to match src/js/interactions.js.
3
+
4
+ export type Target = string | Element;
5
+
6
+ export interface ConfigureOptions {
7
+ /** Namespace for trigger attributes AND class names, e.g. "ui" → data-ui-open / .ui-toast. */
8
+ prefix?: string;
9
+ }
10
+
11
+ export type ToastType = "success" | "warning" | "error" | "info" | "";
12
+
13
+ export interface ToastOptions {
14
+ type?: ToastType;
15
+ /** Auto-dismiss after ms (0 to disable). Default 4000. */
16
+ timeout?: number;
17
+ /** "top-right" (default) or any string containing "bottom". */
18
+ position?: string;
19
+ }
20
+
21
+ /** Namespace the trigger attributes and generated class names. */
22
+ export function configure(opts?: ConfigureOptions): void;
23
+
24
+ /** Install delegated listeners for data-open / data-close / data-toggle and tab roving. */
25
+ export function mount(root?: Document | Element): void;
26
+
27
+ /** Open a stateful component (sets data-state="open" + a11y behaviours). */
28
+ export function open(target: Target): void;
29
+
30
+ /** Close a stateful component. */
31
+ export function close(target: Target): void;
32
+
33
+ /** Toggle a stateful component. */
34
+ export function toggle(target: Target): void;
35
+
36
+ /** Show a toast; returns a dismiss() function. */
37
+ export function toast(message: string, opts?: ToastOptions): () => void;
38
+
39
+ /** Trap Tab focus within an element; returns a cleanup function. */
40
+ export function trapFocus(el: Element): () => void;
41
+
42
+ /** Lock / unlock document scroll (ref-counted). */
43
+ export function lockScroll(): void;
44
+ export function unlockScroll(): void;
45
+
46
+ declare const _default: {
47
+ configure: typeof configure;
48
+ mount: typeof mount;
49
+ open: typeof open;
50
+ close: typeof close;
51
+ toggle: typeof toggle;
52
+ toast: typeof toast;
53
+ trapFocus: typeof trapFocus;
54
+ lockScroll: typeof lockScroll;
55
+ unlockScroll: typeof unlockScroll;
56
+ };
57
+ export default _default;
@@ -0,0 +1 @@
1
+ var Aura=(()=>{var p=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var N=(e,t)=>{for(var s in t)p(e,s,{get:t[s],enumerable:!0})},$=(e,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of _(t))!F.call(e,o)&&o!==s&&p(e,o,{get:()=>t[o],enumerable:!(n=T(t,o))||n.enumerable});return e};var H=e=>$(p({},"__esModule",{value:!0}),e);var R={};N(R,{activateTab:()=>A,close:()=>f,configure:()=>K,lockScroll:()=>S,mount:()=>k,open:()=>E,toast:()=>M,toggle:()=>C,trapFocus:()=>D,unlockScroll:()=>q});var h="",a=e=>`data-${h}${e}`,c=e=>`${h}${e}`;function K(e={}){e.prefix!=null&&(h=e.prefix?e.prefix+"-":"")}var L='a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])',v=new WeakMap,g=0,y=e=>e?typeof e=="string"?document.querySelector(e):e:null,x=e=>e?e.closest("[data-state]"):null;function S(){g++===0&&(document.documentElement.style.overflow="hidden")}function q(){--g<=0&&(g=0,document.documentElement.style.overflow="")}function D(e){let t=e.querySelectorAll(L);(t[0]||e).focus?.();let s=n=>{if(n.key!=="Tab"||!t.length)return;let o=t[0],r=t[t.length-1];n.shiftKey&&document.activeElement===o?(n.preventDefault(),r.focus()):!n.shiftKey&&document.activeElement===r&&(n.preventDefault(),o.focus())};return e.addEventListener("keydown",s),()=>e.removeEventListener("keydown",s)}function O(e){let t=[],s=n=>{n.key==="Escape"&&f(e)};if(document.addEventListener("keydown",s),t.push(()=>document.removeEventListener("keydown",s)),e.hasAttribute("data-overlay")){let n=r=>{r.target===e&&f(e)};e.addEventListener("click",n),t.push(()=>e.removeEventListener("click",n)),S(),t.push(q);let o=document.activeElement;t.push(D(e)),t.push(()=>o&&o.focus&&o.focus())}else{let n=e.querySelector("["+a("toggle")+"]");n&&(n.setAttribute("aria-expanded","true"),t.push(()=>{n.setAttribute("aria-expanded","false"),n.focus()}));let o=()=>[...e.querySelectorAll(L)].filter(u=>!u.hasAttribute(a("toggle"))),r=o();r.length&&setTimeout(()=>r[0].focus(),0);let i=u=>{if(!["ArrowDown","ArrowUp","Home","End"].includes(u.key))return;let d=o();if(!d.length)return;u.preventDefault();let m=d.indexOf(document.activeElement),b;u.key==="Home"?b=0:u.key==="End"?b=d.length-1:u.key==="ArrowDown"?b=m<0?0:(m+1)%d.length:b=m<=0?d.length-1:m-1,d[b].focus()};e.addEventListener("keydown",i),t.push(()=>e.removeEventListener("keydown",i));let l=u=>{e.contains(u.target)||f(e)};setTimeout(()=>document.addEventListener("click",l),0),t.push(()=>document.removeEventListener("click",l))}v.set(e,()=>t.forEach(n=>n()))}function E(e){let t=y(e);!t||t.getAttribute("data-state")==="open"||(t.setAttribute("data-state","open"),t.dispatchEvent(new CustomEvent("ui:open",{bubbles:!0})),O(t))}function f(e){let t=y(e);if(!t||t.getAttribute("data-state")!=="open")return;t.setAttribute("data-state","closed"),t.dispatchEvent(new CustomEvent("ui:close",{bubbles:!0}));let s=v.get(t);s&&(s(),v.delete(t))}function C(e){let t=y(e);t&&(t.getAttribute("data-state")==="open"?f(t):E(t))}function M(e,t={}){let{type:s="",timeout:n=4e3,position:o="top-right"}=t,r=document.querySelector("[data-toast-container]");r||(r=document.createElement("div"),r.className=c("toast-container")+(o.includes("bottom")?" "+c("toast-container--bottom"):""),r.setAttribute("data-toast-container",""),r.setAttribute("role","region"),r.setAttribute("aria-live","polite"),r.setAttribute("aria-label","Notifications"),document.body.appendChild(r));let i=document.createElement("div");i.className=c("toast")+(s?" "+c("toast--"+s):""),i.setAttribute("data-state","closed"),i.setAttribute("role",s==="error"?"alert":"status"),i.innerHTML='<div class="'+c("toast__body")+'">'+e+'</div><button class="'+c("toast__close")+'" aria-label="Dismiss">&times;</button>',r.appendChild(i),requestAnimationFrame(()=>i.setAttribute("data-state","open"));let l=()=>{i.setAttribute("data-state","closed"),setTimeout(()=>i.remove(),250)};return i.querySelector("."+c("toast__close")).addEventListener("click",l),n&&setTimeout(l,n),l}function A(e){let t=e.closest("."+c("tabs"));t&&t.querySelectorAll("."+c("tab")).forEach(s=>{let n=s===e;s.classList.toggle(c("tab--active"),n),s.setAttribute("aria-selected",n?"true":"false"),s.tabIndex=n?0:-1;let o=s.getAttribute(a("tab"));if(o){let r=document.querySelector(o);r&&(r.hidden=!n)}})}var w=!1;function k(e=document){w||(w=!0,e.addEventListener("click",t=>{let s=t.target.closest("."+c("tab"));if(s&&s.hasAttribute(a("tab")))return A(s);let n=t.target.closest("["+a("open")+"]");if(n)return t.preventDefault(),E(n.getAttribute(a("open")));let o=t.target.closest("["+a("close")+"]");if(o){let i=o.getAttribute(a("close"));return f(i||x(o))}let r=t.target.closest("["+a("toggle")+"]");if(r){t.preventDefault();let i=r.getAttribute(a("toggle"));return C(i||x(r))}}),e.addEventListener("keydown",t=>{if(t.key!=="ArrowRight"&&t.key!=="ArrowLeft")return;let s=t.target.closest("."+c("tab"));if(!s)return;let n=s.closest("."+c("tabs"));if(!n)return;let o=[...n.querySelectorAll("."+c("tab"))],r=o.indexOf(s);t.preventDefault();let i=t.key==="ArrowRight"?(r+1)%o.length:(r-1+o.length)%o.length;o[i].focus(),o[i].hasAttribute(a("tab"))&&A(o[i])}))}k();return H(R);})();
@@ -0,0 +1 @@
1
+ var A="",a=e=>`data-${A}${e}`,c=e=>`${A}${e}`;function D(e={}){e.prefix!=null&&(A=e.prefix?e.prefix+"-":"")}var x='a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])',m=new WeakMap,v=0,h=e=>e?typeof e=="string"?document.querySelector(e):e:null,E=e=>e?e.closest("[data-state]"):null;function w(){v++===0&&(document.documentElement.style.overflow="hidden")}function L(){--v<=0&&(v=0,document.documentElement.style.overflow="")}function S(e){let t=e.querySelectorAll(x);(t[0]||e).focus?.();let s=n=>{if(n.key!=="Tab"||!t.length)return;let r=t[0],o=t[t.length-1];n.shiftKey&&document.activeElement===r?(n.preventDefault(),o.focus()):!n.shiftKey&&document.activeElement===o&&(n.preventDefault(),r.focus())};return e.addEventListener("keydown",s),()=>e.removeEventListener("keydown",s)}function C(e){let t=[],s=n=>{n.key==="Escape"&&f(e)};if(document.addEventListener("keydown",s),t.push(()=>document.removeEventListener("keydown",s)),e.hasAttribute("data-overlay")){let n=o=>{o.target===e&&f(e)};e.addEventListener("click",n),t.push(()=>e.removeEventListener("click",n)),w(),t.push(L);let r=document.activeElement;t.push(S(e)),t.push(()=>r&&r.focus&&r.focus())}else{let n=e.querySelector("["+a("toggle")+"]");n&&(n.setAttribute("aria-expanded","true"),t.push(()=>{n.setAttribute("aria-expanded","false"),n.focus()}));let r=()=>[...e.querySelectorAll(x)].filter(u=>!u.hasAttribute(a("toggle"))),o=r();o.length&&setTimeout(()=>o[0].focus(),0);let i=u=>{if(!["ArrowDown","ArrowUp","Home","End"].includes(u.key))return;let d=r();if(!d.length)return;u.preventDefault();let p=d.indexOf(document.activeElement),b;u.key==="Home"?b=0:u.key==="End"?b=d.length-1:u.key==="ArrowDown"?b=p<0?0:(p+1)%d.length:b=p<=0?d.length-1:p-1,d[b].focus()};e.addEventListener("keydown",i),t.push(()=>e.removeEventListener("keydown",i));let l=u=>{e.contains(u.target)||f(e)};setTimeout(()=>document.addEventListener("click",l),0),t.push(()=>document.removeEventListener("click",l))}m.set(e,()=>t.forEach(n=>n()))}function y(e){let t=h(e);!t||t.getAttribute("data-state")==="open"||(t.setAttribute("data-state","open"),t.dispatchEvent(new CustomEvent("ui:open",{bubbles:!0})),C(t))}function f(e){let t=h(e);if(!t||t.getAttribute("data-state")!=="open")return;t.setAttribute("data-state","closed"),t.dispatchEvent(new CustomEvent("ui:close",{bubbles:!0}));let s=m.get(t);s&&(s(),m.delete(t))}function q(e){let t=h(e);t&&(t.getAttribute("data-state")==="open"?f(t):y(t))}function T(e,t={}){let{type:s="",timeout:n=4e3,position:r="top-right"}=t,o=document.querySelector("[data-toast-container]");o||(o=document.createElement("div"),o.className=c("toast-container")+(r.includes("bottom")?" "+c("toast-container--bottom"):""),o.setAttribute("data-toast-container",""),o.setAttribute("role","region"),o.setAttribute("aria-live","polite"),o.setAttribute("aria-label","Notifications"),document.body.appendChild(o));let i=document.createElement("div");i.className=c("toast")+(s?" "+c("toast--"+s):""),i.setAttribute("data-state","closed"),i.setAttribute("role",s==="error"?"alert":"status"),i.innerHTML='<div class="'+c("toast__body")+'">'+e+'</div><button class="'+c("toast__close")+'" aria-label="Dismiss">&times;</button>',o.appendChild(i),requestAnimationFrame(()=>i.setAttribute("data-state","open"));let l=()=>{i.setAttribute("data-state","closed"),setTimeout(()=>i.remove(),250)};return i.querySelector("."+c("toast__close")).addEventListener("click",l),n&&setTimeout(l,n),l}function g(e){let t=e.closest("."+c("tabs"));t&&t.querySelectorAll("."+c("tab")).forEach(s=>{let n=s===e;s.classList.toggle(c("tab--active"),n),s.setAttribute("aria-selected",n?"true":"false"),s.tabIndex=n?0:-1;let r=s.getAttribute(a("tab"));if(r){let o=document.querySelector(r);o&&(o.hidden=!n)}})}var k=!1;function _(e=document){k||(k=!0,e.addEventListener("click",t=>{let s=t.target.closest("."+c("tab"));if(s&&s.hasAttribute(a("tab")))return g(s);let n=t.target.closest("["+a("open")+"]");if(n)return t.preventDefault(),y(n.getAttribute(a("open")));let r=t.target.closest("["+a("close")+"]");if(r){let i=r.getAttribute(a("close"));return f(i||E(r))}let o=t.target.closest("["+a("toggle")+"]");if(o){t.preventDefault();let i=o.getAttribute(a("toggle"));return q(i||E(o))}}),e.addEventListener("keydown",t=>{if(t.key!=="ArrowRight"&&t.key!=="ArrowLeft")return;let s=t.target.closest("."+c("tab"));if(!s)return;let n=s.closest("."+c("tabs"));if(!n)return;let r=[...n.querySelectorAll("."+c("tab"))],o=r.indexOf(s);t.preventDefault();let i=t.key==="ArrowRight"?(o+1)%r.length:(o-1+r.length)%r.length;r[i].focus(),r[i].hasAttribute(a("tab"))&&g(r[i])}))}var F={configure:D,mount:_,open:y,close:f,toggle:q,toast:T,activateTab:g,trapFocus:S,lockScroll:w,unlockScroll:L};export{g as activateTab,f as close,D as configure,F as default,w as lockScroll,_ as mount,y as open,T as toast,q as toggle,S as trapFocus,L as unlockScroll};
@@ -0,0 +1,208 @@
1
+ // src/js/interactions.js
2
+ var PFX = "";
3
+ var A = (name) => `data-${PFX}${name}`;
4
+ var C = (name) => `${PFX}${name}`;
5
+ function configure(opts = {}) {
6
+ if (opts.prefix != null) PFX = opts.prefix ? opts.prefix + "-" : "";
7
+ }
8
+ var FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
9
+ var cleanups = /* @__PURE__ */ new WeakMap();
10
+ var scrollLocks = 0;
11
+ var resolve = (t) => !t ? null : typeof t === "string" ? document.querySelector(t) : t;
12
+ var stateEl = (el) => el ? el.closest("[data-state]") : null;
13
+ function lockScroll() {
14
+ if (scrollLocks++ === 0) document.documentElement.style.overflow = "hidden";
15
+ }
16
+ function unlockScroll() {
17
+ if (--scrollLocks <= 0) {
18
+ scrollLocks = 0;
19
+ document.documentElement.style.overflow = "";
20
+ }
21
+ }
22
+ function trapFocus(el) {
23
+ const nodes = el.querySelectorAll(FOCUSABLE);
24
+ (nodes[0] || el).focus?.();
25
+ const onKey = (e) => {
26
+ if (e.key !== "Tab" || !nodes.length) return;
27
+ const first = nodes[0], last = nodes[nodes.length - 1];
28
+ if (e.shiftKey && document.activeElement === first) {
29
+ e.preventDefault();
30
+ last.focus();
31
+ } else if (!e.shiftKey && document.activeElement === last) {
32
+ e.preventDefault();
33
+ first.focus();
34
+ }
35
+ };
36
+ el.addEventListener("keydown", onKey);
37
+ return () => el.removeEventListener("keydown", onKey);
38
+ }
39
+ function activate(el) {
40
+ const teardown = [];
41
+ const onEsc = (e) => {
42
+ if (e.key === "Escape") close(el);
43
+ };
44
+ document.addEventListener("keydown", onEsc);
45
+ teardown.push(() => document.removeEventListener("keydown", onEsc));
46
+ if (el.hasAttribute("data-overlay")) {
47
+ const onClick = (e) => {
48
+ if (e.target === el) close(el);
49
+ };
50
+ el.addEventListener("click", onClick);
51
+ teardown.push(() => el.removeEventListener("click", onClick));
52
+ lockScroll();
53
+ teardown.push(unlockScroll);
54
+ const prev = document.activeElement;
55
+ teardown.push(trapFocus(el));
56
+ teardown.push(() => prev && prev.focus && prev.focus());
57
+ } else {
58
+ const trg = el.querySelector("[" + A("toggle") + "]");
59
+ if (trg) {
60
+ trg.setAttribute("aria-expanded", "true");
61
+ teardown.push(() => {
62
+ trg.setAttribute("aria-expanded", "false");
63
+ trg.focus();
64
+ });
65
+ }
66
+ const items = () => [...el.querySelectorAll(FOCUSABLE)].filter((n) => !n.hasAttribute(A("toggle")));
67
+ const list = items();
68
+ if (list.length) setTimeout(() => list[0].focus(), 0);
69
+ const onNav = (e) => {
70
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(e.key)) return;
71
+ const l = items();
72
+ if (!l.length) return;
73
+ e.preventDefault();
74
+ const i = l.indexOf(document.activeElement);
75
+ let n;
76
+ if (e.key === "Home") n = 0;
77
+ else if (e.key === "End") n = l.length - 1;
78
+ else if (e.key === "ArrowDown") n = i < 0 ? 0 : (i + 1) % l.length;
79
+ else n = i <= 0 ? l.length - 1 : i - 1;
80
+ l[n].focus();
81
+ };
82
+ el.addEventListener("keydown", onNav);
83
+ teardown.push(() => el.removeEventListener("keydown", onNav));
84
+ const onDoc = (e) => {
85
+ if (!el.contains(e.target)) close(el);
86
+ };
87
+ setTimeout(() => document.addEventListener("click", onDoc), 0);
88
+ teardown.push(() => document.removeEventListener("click", onDoc));
89
+ }
90
+ cleanups.set(el, () => teardown.forEach((fn) => fn()));
91
+ }
92
+ function open(target) {
93
+ const el = resolve(target);
94
+ if (!el || el.getAttribute("data-state") === "open") return;
95
+ el.setAttribute("data-state", "open");
96
+ el.dispatchEvent(new CustomEvent("ui:open", { bubbles: true }));
97
+ activate(el);
98
+ }
99
+ function close(target) {
100
+ const el = resolve(target);
101
+ if (!el || el.getAttribute("data-state") !== "open") return;
102
+ el.setAttribute("data-state", "closed");
103
+ el.dispatchEvent(new CustomEvent("ui:close", { bubbles: true }));
104
+ const t = cleanups.get(el);
105
+ if (t) {
106
+ t();
107
+ cleanups.delete(el);
108
+ }
109
+ }
110
+ function toggle(target) {
111
+ const el = resolve(target);
112
+ if (!el) return;
113
+ el.getAttribute("data-state") === "open" ? close(el) : open(el);
114
+ }
115
+ function toast(message, opts = {}) {
116
+ const { type = "", timeout = 4e3, position = "top-right" } = opts;
117
+ let c = document.querySelector("[data-toast-container]");
118
+ if (!c) {
119
+ c = document.createElement("div");
120
+ c.className = C("toast-container") + (position.includes("bottom") ? " " + C("toast-container--bottom") : "");
121
+ c.setAttribute("data-toast-container", "");
122
+ c.setAttribute("role", "region");
123
+ c.setAttribute("aria-live", "polite");
124
+ c.setAttribute("aria-label", "Notifications");
125
+ document.body.appendChild(c);
126
+ }
127
+ const el = document.createElement("div");
128
+ el.className = C("toast") + (type ? " " + C("toast--" + type) : "");
129
+ el.setAttribute("data-state", "closed");
130
+ el.setAttribute("role", type === "error" ? "alert" : "status");
131
+ el.innerHTML = '<div class="' + C("toast__body") + '">' + message + '</div><button class="' + C("toast__close") + '" aria-label="Dismiss">&times;</button>';
132
+ c.appendChild(el);
133
+ requestAnimationFrame(() => el.setAttribute("data-state", "open"));
134
+ const dismiss = () => {
135
+ el.setAttribute("data-state", "closed");
136
+ setTimeout(() => el.remove(), 250);
137
+ };
138
+ el.querySelector("." + C("toast__close")).addEventListener("click", dismiss);
139
+ if (timeout) setTimeout(dismiss, timeout);
140
+ return dismiss;
141
+ }
142
+ function activateTab(tab) {
143
+ const bar = tab.closest("." + C("tabs"));
144
+ if (!bar) return;
145
+ bar.querySelectorAll("." + C("tab")).forEach((t) => {
146
+ const on = t === tab;
147
+ t.classList.toggle(C("tab--active"), on);
148
+ t.setAttribute("aria-selected", on ? "true" : "false");
149
+ t.tabIndex = on ? 0 : -1;
150
+ const sel = t.getAttribute(A("tab"));
151
+ if (sel) {
152
+ const p = document.querySelector(sel);
153
+ if (p) p.hidden = !on;
154
+ }
155
+ });
156
+ }
157
+ var mounted = false;
158
+ function mount(root = document) {
159
+ if (mounted) return;
160
+ mounted = true;
161
+ root.addEventListener("click", (e) => {
162
+ const tabEl = e.target.closest("." + C("tab"));
163
+ if (tabEl && tabEl.hasAttribute(A("tab"))) return activateTab(tabEl);
164
+ const o = e.target.closest("[" + A("open") + "]");
165
+ if (o) {
166
+ e.preventDefault();
167
+ return open(o.getAttribute(A("open")));
168
+ }
169
+ const c = e.target.closest("[" + A("close") + "]");
170
+ if (c) {
171
+ const t2 = c.getAttribute(A("close"));
172
+ return close(t2 || stateEl(c));
173
+ }
174
+ const t = e.target.closest("[" + A("toggle") + "]");
175
+ if (t) {
176
+ e.preventDefault();
177
+ const v = t.getAttribute(A("toggle"));
178
+ return toggle(v || stateEl(t));
179
+ }
180
+ });
181
+ root.addEventListener("keydown", (e) => {
182
+ if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
183
+ const tab = e.target.closest("." + C("tab"));
184
+ if (!tab) return;
185
+ const bar = tab.closest("." + C("tabs"));
186
+ if (!bar) return;
187
+ const tabs = [...bar.querySelectorAll("." + C("tab"))];
188
+ const i = tabs.indexOf(tab);
189
+ e.preventDefault();
190
+ const n = e.key === "ArrowRight" ? (i + 1) % tabs.length : (i - 1 + tabs.length) % tabs.length;
191
+ tabs[n].focus();
192
+ if (tabs[n].hasAttribute(A("tab"))) activateTab(tabs[n]);
193
+ });
194
+ }
195
+ var interactions_default = { configure, mount, open, close, toggle, toast, activateTab, trapFocus, lockScroll, unlockScroll };
196
+ export {
197
+ activateTab,
198
+ close,
199
+ configure,
200
+ interactions_default as default,
201
+ lockScroll,
202
+ mount,
203
+ open,
204
+ toast,
205
+ toggle,
206
+ trapFocus,
207
+ unlockScroll
208
+ };
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@oleksandr-94/aura-css",
3
+ "version": "0.1.0",
4
+ "description": "Aura — a framework-agnostic, themeable, skinnable CSS component library (SCSS source + optional JS behaviour layer).",
5
+ "license": "MIT",
6
+ "publishConfig": { "access": "public" },
7
+ "repository": { "type": "git", "url": "git+https://github.com/oleksandr-94/aura-css.git" },
8
+ "homepage": "https://github.com/oleksandr-94/aura-css#readme",
9
+ "bugs": "https://github.com/oleksandr-94/aura-css/issues",
10
+ "keywords": [
11
+ "css",
12
+ "components",
13
+ "design-system",
14
+ "themeable",
15
+ "glassmorphism",
16
+ "neumorphism",
17
+ "sass",
18
+ "ui"
19
+ ],
20
+ "type": "module",
21
+ "main": "./dist/interactions.mjs",
22
+ "module": "./dist/interactions.mjs",
23
+ "types": "./dist/interactions.d.ts",
24
+ "sass": "./src/index.scss",
25
+ "style": "./dist/aura.css",
26
+ "files": [
27
+ "dist",
28
+ "src"
29
+ ],
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/interactions.d.ts",
33
+ "import": "./dist/interactions.mjs"
34
+ },
35
+ "./global": "./dist/interactions.global.min.js",
36
+ "./css": "./dist/aura.css",
37
+ "./css/min": "./dist/aura.min.css",
38
+ "./flat": "./dist/aura-flat.css",
39
+ "./flat/min": "./dist/aura-flat.min.css",
40
+ "./neu": "./dist/aura-neu.css",
41
+ "./neu/min": "./dist/aura-neu.min.css",
42
+ "./scss": "./src/index.scss"
43
+ },
44
+ "browserslist": [
45
+ "Chrome >= 111",
46
+ "Edge >= 111",
47
+ "Firefox >= 113",
48
+ "Safari >= 16.4"
49
+ ],
50
+ "scripts": {
51
+ "css:glass": "sass src/index.scss dist/aura.css --style=expanded --no-source-map && sass src/index.scss dist/aura.min.css --style=compressed --no-source-map",
52
+ "css:flat": "sass builds/flat.scss dist/aura-flat.css --style=expanded --no-source-map && sass builds/flat.scss dist/aura-flat.min.css --style=compressed --no-source-map",
53
+ "css:neu": "sass builds/neu.scss dist/aura-neu.css --style=expanded --no-source-map && sass builds/neu.scss dist/aura-neu.min.css --style=compressed --no-source-map",
54
+ "css:prefix": "postcss dist/aura.css dist/aura.min.css dist/aura-flat.css dist/aura-flat.min.css dist/aura-neu.css dist/aura-neu.min.css --replace",
55
+ "build:css": "npm run css:glass && npm run css:flat && npm run css:neu && npm run css:prefix",
56
+ "build:js": "esbuild src/js/interactions.js --bundle --format=esm --outfile=dist/interactions.mjs && esbuild src/js/interactions.js --bundle --format=esm --minify --outfile=dist/interactions.min.mjs && esbuild src/js/global.js --bundle --format=iife --global-name=Aura --minify --outfile=dist/interactions.global.min.js",
57
+ "build": "npm run build:css && npm run build:js",
58
+ "watch": "sass --watch src/index.scss:dist/aura.css --no-source-map",
59
+ "test": "vitest run",
60
+ "test:watch": "vitest",
61
+ "prepublishOnly": "npm run build && npm test"
62
+ },
63
+ "devDependencies": {
64
+ "autoprefixer": "^10.4.19",
65
+ "esbuild": "^0.23.1",
66
+ "happy-dom": "^15.7.4",
67
+ "postcss": "^8.4.38",
68
+ "postcss-cli": "^11.0.0",
69
+ "sass": "^1.77.0",
70
+ "vitest": "^2.1.1"
71
+ }
72
+ }
@@ -0,0 +1,72 @@
1
+ // ============================================================
2
+ // Aura — configuration
3
+ // The three levers that adapt the library per project.
4
+ // Override any of these with `@use "aura/src/config" with (...)`.
5
+ // ============================================================
6
+
7
+ // 1) Namespace. Empty by default; set e.g. "au-" to avoid
8
+ // class-name collisions with other libraries in a project.
9
+ $prefix: '' !default;
10
+
11
+ // 2) Skin — surface treatment, independent of colour palette.
12
+ // glass | flat | neu
13
+ $skin: glass !default;
14
+
15
+ // 3) Themes — colour palettes (Material-3 style roles).
16
+ // Only base colours are required; every `on-*` (content) colour
17
+ // is derived automatically for guaranteed contrast.
18
+ $default-theme: aura-dark !default;
19
+
20
+ $themes: (
21
+ aura-dark: (
22
+ // accents
23
+ primary: #00BD7D,
24
+ secondary: #3B82F6,
25
+ accent: #12E0C0,
26
+ // status
27
+ success: #16A34A,
28
+ warning: #E0913A,
29
+ error: #EA4B5E,
30
+ info: #3B82F6,
31
+ // surfaces (page → elevated)
32
+ surface: #0e1526,
33
+ surface-1: #141d33,
34
+ surface-2: #1b2540,
35
+ on-surface: #e7ecf5,
36
+ on-surface-muted: rgba(231,236,245,.62),
37
+ // lines
38
+ outline: rgba(255,255,255,.14),
39
+ outline-strong: rgba(255,255,255,.24),
40
+ // frosted-glass film (used only by the glass skin)
41
+ glass-film: rgba(255,255,255,.06),
42
+ glass-film-2: rgba(255,255,255,.10),
43
+ // inverted tooltip (light on dark)
44
+ tip-bg: rgba(238,244,250,.96),
45
+ tip-text: #0e1526,
46
+ // elevation
47
+ shadow-1: (0 8px 32px rgba(0,0,0,.40)),
48
+ shadow-2: (0 16px 44px rgba(0,0,0,.50)),
49
+ ),
50
+ aura-light: (
51
+ primary: #00A86B,
52
+ secondary: #2563EB,
53
+ accent: #0FB89B,
54
+ success: #16A34A,
55
+ warning: #D97706,
56
+ error: #DC2626,
57
+ info: #2563EB,
58
+ surface: #eef3f2,
59
+ surface-1: #ffffff,
60
+ surface-2: #f5faf8,
61
+ on-surface: #10231b,
62
+ on-surface-muted: rgba(16,35,27,.62),
63
+ outline: rgba(12,70,50,.16),
64
+ outline-strong: rgba(12,70,50,.30),
65
+ glass-film: rgba(255,255,255,.55),
66
+ glass-film-2: rgba(255,255,255,.70),
67
+ tip-bg: rgba(16,24,40,.95),
68
+ tip-text: #eef4fa,
69
+ shadow-1: (0 10px 30px rgba(10,90,60,.14)),
70
+ shadow-2: (0 16px 40px rgba(10,90,60,.18)),
71
+ ),
72
+ ) !default;
@@ -0,0 +1,23 @@
1
+ // ============================================================
2
+ // Aura — functions
3
+ // Auto content-colour derivation (the "no white-on-white" guard).
4
+ // ============================================================
5
+ @use "sass:color";
6
+ @use "sass:math";
7
+
8
+ // Relative luminance (WCAG-ish, linearised enough for a threshold).
9
+ @function luminance($c) {
10
+ $r: math.div(color.channel($c, "red", $space: rgb), 255);
11
+ $g: math.div(color.channel($c, "green", $space: rgb), 255);
12
+ $b: math.div(color.channel($c, "blue", $space: rgb), 255);
13
+ @return (0.2126 * $r) + (0.7152 * $g) + (0.0722 * $b);
14
+ }
15
+
16
+ // Pick a legible text/icon colour for a given background.
17
+ // Light backgrounds → near-black ink; dark backgrounds → white.
18
+ @function on-color($bg, $dark: #0f1a14, $light: #ffffff) {
19
+ @if luminance($bg) > 0.55 {
20
+ @return $dark;
21
+ }
22
+ @return $light;
23
+ }
@@ -0,0 +1,4 @@
1
+ // Declares cascade-layer order up front. Host app styles stay
2
+ // unlayered and therefore always win over Aura. The a11y layer is
3
+ // last so reduced-motion overrides Aura's own component motion.
4
+ @layer base, components, a11y;
@@ -0,0 +1,49 @@
1
+ // ============================================================
2
+ // Aura — surface dispatcher
3
+ // Components call surface()/field(); this routes to the active
4
+ // skin in skins/. Add a skin = add a file + one branch here.
5
+ // ============================================================
6
+ @use "./config" as cfg;
7
+ @use "./skins/glass";
8
+ @use "./skins/flat";
9
+ @use "./skins/neu";
10
+
11
+ // $level: 1 = card, 2 = elevated (popover / modal)
12
+ @mixin surface($level: 1) {
13
+ @if cfg.$skin == glass { @include glass.surface($level); }
14
+ @else if cfg.$skin == flat { @include flat.surface($level); }
15
+ @else if cfg.$skin == neu { @include neu.surface($level); }
16
+ @else { @error "Unknown $skin: #{cfg.$skin}. Use glass | flat | neu."; }
17
+ }
18
+
19
+ // A control field (input wells, switch tracks).
20
+ @mixin field {
21
+ @if cfg.$skin == glass { @include glass.field; }
22
+ @else if cfg.$skin == flat { @include flat.field; }
23
+ @else if cfg.$skin == neu { @include neu.field; }
24
+ @else { @error "Unknown $skin: #{cfg.$skin}. Use glass | flat | neu."; }
25
+ }
26
+
27
+ // A filled interactive control (buttons). Expects local --_bg / --_fg.
28
+ @mixin control {
29
+ @if cfg.$skin == glass { @include glass.control; }
30
+ @else if cfg.$skin == flat { @include flat.control; }
31
+ @else if cfg.$skin == neu { @include neu.control; }
32
+ @else { @error "Unknown $skin: #{cfg.$skin}. Use glass | flat | neu."; }
33
+ }
34
+
35
+ // Pressed state for a filled control.
36
+ @mixin control-active {
37
+ @if cfg.$skin == glass { @include glass.control-active; }
38
+ @else if cfg.$skin == flat { @include flat.control-active; }
39
+ @else if cfg.$skin == neu { @include neu.control-active; }
40
+ @else { @error "Unknown $skin: #{cfg.$skin}. Use glass | flat | neu."; }
41
+ }
42
+
43
+ // A small tinted pill (badge). Keeps its colour tint; skin adds feel.
44
+ @mixin chip {
45
+ @if cfg.$skin == glass { @include glass.chip; }
46
+ @else if cfg.$skin == flat { @include flat.chip; }
47
+ @else if cfg.$skin == neu { @include neu.chip; }
48
+ @else { @error "Unknown $skin: #{cfg.$skin}. Use glass | flat | neu."; }
49
+ }