@orange-halo/components 1.0.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 (138) hide show
  1. package/custom-elements.json +186 -0
  2. package/dist/base.d.ts +30 -0
  3. package/dist/base.d.ts.map +1 -0
  4. package/dist/base.js +78 -0
  5. package/dist/base.js.map +1 -0
  6. package/dist/index.d.ts +83 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +72 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/oh-accordion.d.ts +47 -0
  11. package/dist/oh-accordion.d.ts.map +1 -0
  12. package/dist/oh-accordion.js +387 -0
  13. package/dist/oh-accordion.js.map +1 -0
  14. package/dist/oh-alert.d.ts +48 -0
  15. package/dist/oh-alert.d.ts.map +1 -0
  16. package/dist/oh-alert.js +343 -0
  17. package/dist/oh-alert.js.map +1 -0
  18. package/dist/oh-badge.d.ts +38 -0
  19. package/dist/oh-badge.d.ts.map +1 -0
  20. package/dist/oh-badge.js +176 -0
  21. package/dist/oh-badge.js.map +1 -0
  22. package/dist/oh-breadcrumb.d.ts +39 -0
  23. package/dist/oh-breadcrumb.d.ts.map +1 -0
  24. package/dist/oh-breadcrumb.js +277 -0
  25. package/dist/oh-breadcrumb.js.map +1 -0
  26. package/dist/oh-button.d.ts +62 -0
  27. package/dist/oh-button.d.ts.map +1 -0
  28. package/dist/oh-button.figma.d.ts +2 -0
  29. package/dist/oh-button.figma.d.ts.map +1 -0
  30. package/dist/oh-button.figma.js +20 -0
  31. package/dist/oh-button.figma.js.map +1 -0
  32. package/dist/oh-button.js +490 -0
  33. package/dist/oh-button.js.map +1 -0
  34. package/dist/oh-card.d.ts +44 -0
  35. package/dist/oh-card.d.ts.map +1 -0
  36. package/dist/oh-card.js +340 -0
  37. package/dist/oh-card.js.map +1 -0
  38. package/dist/oh-checkbox-group.d.ts +39 -0
  39. package/dist/oh-checkbox-group.d.ts.map +1 -0
  40. package/dist/oh-checkbox-group.figma.d.ts +2 -0
  41. package/dist/oh-checkbox-group.figma.d.ts.map +1 -0
  42. package/dist/oh-checkbox-group.figma.js +24 -0
  43. package/dist/oh-checkbox-group.figma.js.map +1 -0
  44. package/dist/oh-checkbox-group.js +309 -0
  45. package/dist/oh-checkbox-group.js.map +1 -0
  46. package/dist/oh-checkbox.d.ts +50 -0
  47. package/dist/oh-checkbox.d.ts.map +1 -0
  48. package/dist/oh-checkbox.js +315 -0
  49. package/dist/oh-checkbox.js.map +1 -0
  50. package/dist/oh-cluster.d.ts +38 -0
  51. package/dist/oh-cluster.d.ts.map +1 -0
  52. package/dist/oh-cluster.js +141 -0
  53. package/dist/oh-cluster.js.map +1 -0
  54. package/dist/oh-container.d.ts +38 -0
  55. package/dist/oh-container.d.ts.map +1 -0
  56. package/dist/oh-container.js +116 -0
  57. package/dist/oh-container.js.map +1 -0
  58. package/dist/oh-drawer.d.ts +66 -0
  59. package/dist/oh-drawer.d.ts.map +1 -0
  60. package/dist/oh-drawer.js +284 -0
  61. package/dist/oh-drawer.js.map +1 -0
  62. package/dist/oh-footer.d.ts +40 -0
  63. package/dist/oh-footer.d.ts.map +1 -0
  64. package/dist/oh-footer.js +112 -0
  65. package/dist/oh-footer.js.map +1 -0
  66. package/dist/oh-grid.d.ts +40 -0
  67. package/dist/oh-grid.d.ts.map +1 -0
  68. package/dist/oh-grid.js +168 -0
  69. package/dist/oh-grid.js.map +1 -0
  70. package/dist/oh-hero.d.ts +28 -0
  71. package/dist/oh-hero.d.ts.map +1 -0
  72. package/dist/oh-hero.js +242 -0
  73. package/dist/oh-hero.js.map +1 -0
  74. package/dist/oh-icon.d.ts +44 -0
  75. package/dist/oh-icon.d.ts.map +1 -0
  76. package/dist/oh-icon.js +321 -0
  77. package/dist/oh-icon.js.map +1 -0
  78. package/dist/oh-input.d.ts +56 -0
  79. package/dist/oh-input.d.ts.map +1 -0
  80. package/dist/oh-input.figma.d.ts +2 -0
  81. package/dist/oh-input.figma.d.ts.map +1 -0
  82. package/dist/oh-input.figma.js +36 -0
  83. package/dist/oh-input.figma.js.map +1 -0
  84. package/dist/oh-input.js +320 -0
  85. package/dist/oh-input.js.map +1 -0
  86. package/dist/oh-link.d.ts +45 -0
  87. package/dist/oh-link.d.ts.map +1 -0
  88. package/dist/oh-link.js +392 -0
  89. package/dist/oh-link.js.map +1 -0
  90. package/dist/oh-modal.d.ts +54 -0
  91. package/dist/oh-modal.d.ts.map +1 -0
  92. package/dist/oh-modal.js +450 -0
  93. package/dist/oh-modal.js.map +1 -0
  94. package/dist/oh-navbar.d.ts +49 -0
  95. package/dist/oh-navbar.d.ts.map +1 -0
  96. package/dist/oh-navbar.js +185 -0
  97. package/dist/oh-navbar.js.map +1 -0
  98. package/dist/oh-progress.d.ts +56 -0
  99. package/dist/oh-progress.d.ts.map +1 -0
  100. package/dist/oh-progress.js +299 -0
  101. package/dist/oh-progress.js.map +1 -0
  102. package/dist/oh-radio-group.d.ts +43 -0
  103. package/dist/oh-radio-group.d.ts.map +1 -0
  104. package/dist/oh-radio-group.figma.d.ts +2 -0
  105. package/dist/oh-radio-group.figma.d.ts.map +1 -0
  106. package/dist/oh-radio-group.figma.js +22 -0
  107. package/dist/oh-radio-group.figma.js.map +1 -0
  108. package/dist/oh-radio-group.js +324 -0
  109. package/dist/oh-radio-group.js.map +1 -0
  110. package/dist/oh-radio.d.ts +50 -0
  111. package/dist/oh-radio.d.ts.map +1 -0
  112. package/dist/oh-radio.js +314 -0
  113. package/dist/oh-radio.js.map +1 -0
  114. package/dist/oh-select.d.ts +82 -0
  115. package/dist/oh-select.d.ts.map +1 -0
  116. package/dist/oh-select.js +638 -0
  117. package/dist/oh-select.js.map +1 -0
  118. package/dist/oh-skip-link.d.ts +37 -0
  119. package/dist/oh-skip-link.d.ts.map +1 -0
  120. package/dist/oh-skip-link.js +145 -0
  121. package/dist/oh-skip-link.js.map +1 -0
  122. package/dist/oh-stack.d.ts +36 -0
  123. package/dist/oh-stack.d.ts.map +1 -0
  124. package/dist/oh-stack.js +112 -0
  125. package/dist/oh-stack.js.map +1 -0
  126. package/dist/oh-tabs.d.ts +85 -0
  127. package/dist/oh-tabs.d.ts.map +1 -0
  128. package/dist/oh-tabs.js +417 -0
  129. package/dist/oh-tabs.js.map +1 -0
  130. package/dist/oh-toggle.d.ts +51 -0
  131. package/dist/oh-toggle.d.ts.map +1 -0
  132. package/dist/oh-toggle.js +219 -0
  133. package/dist/oh-toggle.js.map +1 -0
  134. package/dist/styles/typography.d.ts +15 -0
  135. package/dist/styles/typography.d.ts.map +1 -0
  136. package/dist/styles/typography.js +235 -0
  137. package/dist/styles/typography.js.map +1 -0
  138. package/package.json +140 -0
@@ -0,0 +1,490 @@
1
+ /**
2
+ * oh-button
3
+ *
4
+ * A chunky, confident button with playful personality.
5
+ * Inspired by hand-crafted, illustrative UI — not corporate SaaS.
6
+ *
7
+ * DESIGN DECISIONS:
8
+ * ─────────────────
9
+ * 1. CHUNKY & CONFIDENT
10
+ * - Thick border (2px) that feels illustrative
11
+ * - Solid fills, no subtle gradients
12
+ * - Generous padding, substantial presence
13
+ *
14
+ * 2. OFFSET SHADOW (STICKER EFFECT)
15
+ * - Shadow offset to bottom-right
16
+ * - Feels like a physical sticker or stamp
17
+ * - Not a generic centered drop shadow
18
+ *
19
+ * 3. PLAYFUL INTERACTIONS
20
+ * - Hover: slight upward lift + shadow grows
21
+ * - Active: pressed down, shadow shrinks (stamp effect)
22
+ * - Focus: warm glow + accessible underline
23
+ *
24
+ * 4. HAND-CRAFTED FEEL
25
+ * - Bold, defined edges
26
+ * - Confident color choices
27
+ * - Personality over polish
28
+ *
29
+ * @element oh-button
30
+ */
31
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
32
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
33
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
34
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
35
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
36
+ };
37
+ import { html, css, nothing } from "lit";
38
+ import { customElement, property } from "lit/decorators.js";
39
+ import { OhElement, baseStyles } from "./base.js";
40
+ let OhButton = class OhButton extends OhElement {
41
+ constructor() {
42
+ super(...arguments);
43
+ this.variant = "primary";
44
+ this.size = "md";
45
+ this.loading = false;
46
+ this.iconOnly = false;
47
+ /**
48
+ * Force a visual state (for documentation/Figma sync only)
49
+ * Values: 'hover' | 'active' | 'focus'
50
+ */
51
+ this.forceState = "default";
52
+ }
53
+ static { this.styles = [
54
+ baseStyles,
55
+ css `
56
+ /* ═══════════════════════════════════════════════════════════════
57
+ ORANGE HALO BUTTON
58
+ Chunky • Playful • Confident • Hand-crafted
59
+ ═══════════════════════════════════════════════════════════════ */
60
+
61
+ :host {
62
+ display: inline-block;
63
+ }
64
+
65
+ .button {
66
+ /* Typography: friendly, not shouty */
67
+ font-family: var(--oh-font-family-sans);
68
+ font-weight: var(--oh-font-weight-semibold);
69
+ letter-spacing: var(--oh-font-letter-spacing-wide);
70
+ text-decoration: none;
71
+
72
+ /* Layout */
73
+ display: inline-flex;
74
+ align-items: center;
75
+ justify-content: center;
76
+ gap: var(--oh-spacing-2);
77
+
78
+ /* Shape: chunky rounded corners, not pills */
79
+ border-radius: var(--oh-radius-md);
80
+
81
+ /* Thick illustrative border */
82
+ border: var(--oh-button-base-border-width) solid;
83
+
84
+ /* Remove default button styles */
85
+ cursor: pointer;
86
+ -webkit-appearance: none;
87
+ -moz-appearance: none;
88
+ appearance: none;
89
+
90
+ /* Smooth but snappy transitions */
91
+ transition:
92
+ transform var(--oh-motion-snappy) var(--oh-motion-ease-playful),
93
+ box-shadow var(--oh-motion-snappy) var(--oh-motion-ease-playful),
94
+ background-color var(--oh-motion-quick) ease;
95
+ }
96
+
97
+ /* ═══════════════════════════════════════════════════════════════
98
+ PRIMARY VARIANT
99
+ Signature orange — bold and warm
100
+ Filled button: color + shadow define shape (no visible border)
101
+ Contrast: #FFFFFF on #C54300 = 5.0:1 ✓ (WCAG AA)
102
+ ═══════════════════════════════════════════════════════════════ */
103
+
104
+ .button--primary {
105
+ background-color: var(--oh-color-brand-primary);
106
+ border-color: var(--oh-color-brand-primary);
107
+ color: var(--oh-color-text-on-brand);
108
+
109
+ /* Light offset shadow: makes button pop forward */
110
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-primary);
111
+ }
112
+
113
+ .button--primary:hover {
114
+ background-color: var(--oh-color-brand-primary-hover);
115
+ border-color: var(--oh-color-brand-primary-hover);
116
+ transform: translate(-2px, -2px);
117
+ box-shadow: 6px 6px 0 0 var(--oh-shadow-primary);
118
+ }
119
+
120
+ .button--primary:active {
121
+ background-color: var(--oh-color-brand-primary-active);
122
+ border-color: var(--oh-color-brand-primary-active);
123
+ transform: translate(2px, 2px);
124
+ box-shadow: 1px 1px 0 0 var(--oh-shadow-primary);
125
+ }
126
+
127
+ /* ═══════════════════════════════════════════════════════════════
128
+ SECONDARY VARIANT
129
+ Light button: NEEDS visible border for definition
130
+ ═══════════════════════════════════════════════════════════════ */
131
+
132
+ .button--secondary {
133
+ background-color: var(--oh-color-surface-base);
134
+ border-color: var(--oh-color-border-emphasis);
135
+ color: var(--oh-color-text-primary);
136
+
137
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-secondary);
138
+ }
139
+
140
+ .button--secondary:hover {
141
+ background-color: var(--oh-color-surface-hover);
142
+ transform: translate(-2px, -2px);
143
+ box-shadow: 6px 6px 0 0 var(--oh-shadow-secondary);
144
+ }
145
+
146
+ .button--secondary:active {
147
+ background-color: var(--oh-color-surface-active-pressed);
148
+ transform: translate(2px, 2px);
149
+ box-shadow: 1px 1px 0 0 var(--oh-shadow-secondary);
150
+ }
151
+
152
+ /* ═══════════════════════════════════════════════════════════════
153
+ ACCENT VARIANT
154
+ Calm blue — modern counterbalance to warm orange
155
+ Filled button: color + shadow define shape (no visible border)
156
+ ═══════════════════════════════════════════════════════════════ */
157
+
158
+ .button--accent {
159
+ background-color: var(--oh-color-accent-default);
160
+ border-color: var(--oh-color-accent-default);
161
+ color: var(--oh-color-text-on-accent);
162
+
163
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-accent);
164
+ }
165
+
166
+ .button--accent:hover {
167
+ background-color: var(--oh-color-accent-hover);
168
+ border-color: var(--oh-color-accent-hover);
169
+ transform: translate(-2px, -2px);
170
+ box-shadow: 6px 6px 0 0 var(--oh-shadow-accent);
171
+ }
172
+
173
+ .button--accent:active {
174
+ background-color: var(--oh-color-accent-active);
175
+ border-color: var(--oh-color-accent-active);
176
+ transform: translate(2px, 2px);
177
+ box-shadow: 1px 1px 0 0 var(--oh-shadow-accent);
178
+ }
179
+
180
+ /* ═══════════════════════════════════════════════════════════════
181
+ FOCUS STATE
182
+ Accessible underline (WCAG 1.4.11 & 2.4.7)
183
+ ═══════════════════════════════════════════════════════════════ */
184
+
185
+ .button:focus-visible {
186
+ outline: none;
187
+ text-decoration: underline;
188
+ text-underline-offset: var(--oh-spacing-1);
189
+ }
190
+
191
+ .button--primary:focus-visible {
192
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-primary);
193
+ }
194
+
195
+ .button--secondary:focus-visible {
196
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-secondary);
197
+ }
198
+
199
+ .button--accent:focus-visible {
200
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-accent);
201
+ }
202
+
203
+ /* ═══════════════════════════════════════════════════════════════
204
+ SIZE VARIANTS
205
+ Minimum 16px (1rem) for WCAG readability
206
+ Scale: sm=16px, md=18px, lg=20px
207
+ ═══════════════════════════════════════════════════════════════ */
208
+
209
+ .button--sm {
210
+ font-size: var(--oh-font-size-base);
211
+ padding: var(--oh-spacing-2) var(--oh-spacing-4);
212
+ min-height: 40px;
213
+ gap: var(--oh-spacing-2);
214
+ }
215
+
216
+ .button--md {
217
+ font-size: var(--oh-font-size-lg);
218
+ padding: var(--oh-spacing-3) var(--oh-spacing-6);
219
+ min-height: 48px;
220
+ gap: var(--oh-spacing-2);
221
+ }
222
+
223
+ .button--lg {
224
+ font-size: var(--oh-font-size-xl);
225
+ padding: var(--oh-spacing-4) var(--oh-spacing-8);
226
+ min-height: 56px;
227
+ gap: var(--oh-spacing-2-5);
228
+ }
229
+
230
+ /* ═══════════════════════════════════════════════════════════════
231
+ ICON SUPPORT
232
+ ═══════════════════════════════════════════════════════════════ */
233
+
234
+ ::slotted(svg),
235
+ ::slotted([slot="icon-left"]),
236
+ ::slotted([slot="icon-right"]) {
237
+ width: 1.25em;
238
+ height: 1.25em;
239
+ flex-shrink: 0;
240
+ }
241
+
242
+ :host([icon-only]) .button {
243
+ padding: var(--oh-spacing-3);
244
+ aspect-ratio: 1;
245
+ }
246
+
247
+ :host([icon-only]) .button--sm {
248
+ padding: var(--oh-spacing-2-5);
249
+ min-width: 40px;
250
+ }
251
+
252
+ :host([icon-only]) .button--md {
253
+ padding: var(--oh-spacing-3);
254
+ min-width: 48px;
255
+ }
256
+
257
+ :host([icon-only]) .button--lg {
258
+ padding: var(--oh-spacing-4);
259
+ min-width: 56px;
260
+ }
261
+
262
+ /* Icon-only focus underline */
263
+ :host([icon-only]) .button {
264
+ position: relative;
265
+ }
266
+
267
+ :host([icon-only]) .button::after {
268
+ content: '';
269
+ position: absolute;
270
+ bottom: 4px;
271
+ left: 50%;
272
+ transform: translateX(-50%);
273
+ width: 60%;
274
+ height: 2px;
275
+ background-color: currentColor;
276
+ opacity: 0;
277
+ transition: opacity var(--oh-motion-snappy, 150ms) var(--oh-motion-ease-gentle, ease);
278
+ }
279
+
280
+ :host([icon-only]) .button:focus-visible {
281
+ text-decoration: none;
282
+ }
283
+
284
+ :host([icon-only]) .button:focus-visible::after {
285
+ opacity: 1;
286
+ }
287
+
288
+ /* ═══════════════════════════════════════════════════════════════
289
+ LOADING STATE
290
+ ═══════════════════════════════════════════════════════════════ */
291
+
292
+ .button--loading {
293
+ cursor: wait;
294
+ opacity: 0.8;
295
+ }
296
+
297
+ .spinner {
298
+ width: 1.25em;
299
+ height: 1.25em;
300
+ border: 2px solid currentColor;
301
+ border-top-color: transparent;
302
+ border-radius: 50%;
303
+ animation: spin 0.8s linear infinite;
304
+ }
305
+
306
+ @keyframes spin {
307
+ to { transform: rotate(360deg); }
308
+ }
309
+
310
+ /* ═══════════════════════════════════════════════════════════════
311
+ REDUCED MOTION
312
+ ═══════════════════════════════════════════════════════════════ */
313
+
314
+ @media (prefers-reduced-motion: reduce) {
315
+ .button {
316
+ transition-duration: 0.01ms !important;
317
+ }
318
+
319
+ .button:hover,
320
+ .button:active {
321
+ transform: none !important;
322
+ }
323
+
324
+ .spinner {
325
+ animation-duration: 1.5s;
326
+ }
327
+ }
328
+
329
+ /* ═══════════════════════════════════════════════════════════════
330
+ FORCED STATES (for Figma Sync / documentation)
331
+ ═══════════════════════════════════════════════════════════════ */
332
+
333
+ /* Primary - Forced Hover */
334
+ :host([force-state="hover"]) .button--primary {
335
+ background-color: var(--oh-color-brand-primary-hover);
336
+ border-color: var(--oh-color-brand-primary-hover);
337
+ transform: translate(-2px, -2px);
338
+ box-shadow: 6px 6px 0 0 var(--oh-shadow-primary);
339
+ }
340
+
341
+ /* Primary - Forced Active */
342
+ :host([force-state="active"]) .button--primary {
343
+ background-color: var(--oh-color-brand-primary-active);
344
+ border-color: var(--oh-color-brand-primary-active);
345
+ transform: translate(2px, 2px);
346
+ box-shadow: 1px 1px 0 0 var(--oh-shadow-primary);
347
+ }
348
+
349
+ /* Primary - Forced Focus */
350
+ :host([force-state="focus"]) .button--primary {
351
+ outline: none;
352
+ text-decoration: underline;
353
+ text-underline-offset: var(--oh-spacing-1);
354
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-primary);
355
+ }
356
+
357
+ /* Secondary - Forced Hover */
358
+ :host([force-state="hover"]) .button--secondary {
359
+ background-color: var(--oh-color-surface-hover);
360
+ transform: translate(-2px, -2px);
361
+ box-shadow: 6px 6px 0 0 var(--oh-shadow-secondary);
362
+ }
363
+
364
+ /* Secondary - Forced Active */
365
+ :host([force-state="active"]) .button--secondary {
366
+ background-color: var(--oh-color-surface-active-pressed);
367
+ transform: translate(2px, 2px);
368
+ box-shadow: 1px 1px 0 0 var(--oh-shadow-secondary);
369
+ }
370
+
371
+ /* Secondary - Forced Focus */
372
+ :host([force-state="focus"]) .button--secondary {
373
+ outline: none;
374
+ text-decoration: underline;
375
+ text-underline-offset: var(--oh-spacing-1);
376
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-secondary);
377
+ }
378
+
379
+ /* Accent - Forced Hover */
380
+ :host([force-state="hover"]) .button--accent {
381
+ background-color: var(--oh-color-accent-hover);
382
+ border-color: var(--oh-color-accent-hover);
383
+ transform: translate(-2px, -2px);
384
+ box-shadow: 6px 6px 0 0 var(--oh-shadow-accent);
385
+ }
386
+
387
+ /* Accent - Forced Active */
388
+ :host([force-state="active"]) .button--accent {
389
+ background-color: var(--oh-color-accent-active);
390
+ border-color: var(--oh-color-accent-active);
391
+ transform: translate(2px, 2px);
392
+ box-shadow: 1px 1px 0 0 var(--oh-shadow-accent);
393
+ }
394
+
395
+ /* Accent - Forced Focus */
396
+ :host([force-state="focus"]) .button--accent {
397
+ outline: none;
398
+ text-decoration: underline;
399
+ text-underline-offset: var(--oh-spacing-1);
400
+ box-shadow: 4px 4px 0 0 var(--oh-shadow-accent);
401
+ }
402
+ `,
403
+ ]; }
404
+ _handleClick(event) {
405
+ if (this.loading) {
406
+ event.preventDefault();
407
+ event.stopPropagation();
408
+ return;
409
+ }
410
+ this.emit("oh-click", { originalEvent: event });
411
+ }
412
+ /** Focus the internal button/anchor element */
413
+ focus(options) {
414
+ const inner = this.shadowRoot?.querySelector('.button');
415
+ inner?.focus(options);
416
+ }
417
+ /** Blur the internal button/anchor element */
418
+ blur() {
419
+ const inner = this.shadowRoot?.querySelector('.button');
420
+ inner?.blur();
421
+ }
422
+ render() {
423
+ const classes = this.classMap({
424
+ button: true,
425
+ [`button--${this.variant}`]: true,
426
+ [`button--${this.size}`]: true,
427
+ "button--loading": this.loading,
428
+ });
429
+ const content = this.loading
430
+ ? html `<span class="spinner" aria-hidden="true"></span>`
431
+ : html `
432
+ <slot name="icon-left"></slot>
433
+ <slot></slot>
434
+ <slot name="icon-right"></slot>
435
+ `;
436
+ // Render as anchor if href is provided
437
+ if (this.href) {
438
+ const rel = this.target === "_blank" ? "noopener noreferrer" : undefined;
439
+ return html `
440
+ <a
441
+ part="button"
442
+ class=${classes}
443
+ href=${this.href}
444
+ target=${this.target || nothing}
445
+ rel=${rel || nothing}
446
+ >
447
+ ${content}
448
+ </a>
449
+ `;
450
+ }
451
+ // Render as button
452
+ return html `
453
+ <button
454
+ part="button"
455
+ class=${classes}
456
+ ?disabled=${this.loading}
457
+ aria-busy=${this.loading ? "true" : nothing}
458
+ @click=${this._handleClick}
459
+ >
460
+ ${content}
461
+ </button>
462
+ `;
463
+ }
464
+ };
465
+ __decorate([
466
+ property({ type: String, reflect: true })
467
+ ], OhButton.prototype, "variant", void 0);
468
+ __decorate([
469
+ property({ type: String, reflect: true })
470
+ ], OhButton.prototype, "size", void 0);
471
+ __decorate([
472
+ property({ type: Boolean, reflect: true })
473
+ ], OhButton.prototype, "loading", void 0);
474
+ __decorate([
475
+ property({ type: Boolean, reflect: true, attribute: "icon-only" })
476
+ ], OhButton.prototype, "iconOnly", void 0);
477
+ __decorate([
478
+ property({ type: String, reflect: true, attribute: "force-state" })
479
+ ], OhButton.prototype, "forceState", void 0);
480
+ __decorate([
481
+ property({ type: String })
482
+ ], OhButton.prototype, "href", void 0);
483
+ __decorate([
484
+ property({ type: String })
485
+ ], OhButton.prototype, "target", void 0);
486
+ OhButton = __decorate([
487
+ customElement("oh-button")
488
+ ], OhButton);
489
+ export { OhButton };
490
+ //# sourceMappingURL=oh-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-button.js","sourceRoot":"","sources":["../src/oh-button.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;;;;;AAEH,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAO3C,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,SAAS;IAAhC;;QAkWL,YAAO,GAAkB,SAAS,CAAC;QAGnC,SAAI,GAAe,IAAI,CAAC;QAGxB,YAAO,GAAG,KAAK,CAAC;QAGhB,aAAQ,GAAG,KAAK,CAAC;QAEjB;;;WAGG;QAEH,eAAU,GAAgB,SAAS,CAAC;IA4EtC,CAAC;aA7biB,WAAM,GAAG;QACvB,UAAU;QACV,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2VF;KACF,AA9VqB,CA8VpB;IA6BM,YAAY,CAAC,KAAiB;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,+CAA+C;IACtC,KAAK,CAAC,OAAsB;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAc,SAAS,CAAC,CAAC;QACrE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IAED,8CAA8C;IACrC,IAAI;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAc,SAAS,CAAC,CAAC;QACrE,KAAK,EAAE,IAAI,EAAE,CAAC;IAChB,CAAC;IAED,MAAM;QACJ,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC5B,MAAM,EAAE,IAAI;YACZ,CAAC,WAAW,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI;YACjC,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI;YAC9B,iBAAiB,EAAE,IAAI,CAAC,OAAO;SAChC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO;YAC1B,CAAC,CAAC,IAAI,CAAA,kDAAkD;YACxD,CAAC,CAAC,IAAI,CAAA;;;;SAIH,CAAC;QAEN,uCAAuC;QACvC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;YACzE,OAAO,IAAI,CAAA;;;kBAGC,OAAO;iBACR,IAAI,CAAC,IAAI;mBACP,IAAI,CAAC,MAAM,IAAI,OAAO;gBACzB,GAAG,IAAI,OAAO;;YAElB,OAAO;;OAEZ,CAAC;QACJ,CAAC;QAED,mBAAmB;QACnB,OAAO,IAAI,CAAA;;;gBAGC,OAAO;oBACH,IAAI,CAAC,OAAO;oBACZ,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;iBAClC,IAAI,CAAC,YAAY;;UAExB,OAAO;;KAEZ,CAAC;IACJ,CAAC;;AA3FD;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;yCACP;AAGnC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;sCAClB;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;yCAC3B;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;0CAClD;AAOjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;4CAChC;AAIpC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;sCACb;AAId;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCACX;AA1XL,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CA8bpB"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * oh-card
3
+ *
4
+ * A tactile, raised surface with visible frame.
5
+ * Designed with the same layered construction as oh-button.
6
+ *
7
+ * DESIGN DECISIONS:
8
+ * ─────────────────
9
+ * 1. LAYERED CONSTRUCTION
10
+ * - Surface: subtle gradient for depth
11
+ * - Border: visible warm edge
12
+ * - Inner highlight: sunlit top edge
13
+ * - Outer shadow: soft, slightly offset
14
+ *
15
+ * 2. RETRO-MODERN DETAILS
16
+ * - Warm, tactile shadows (never harsh)
17
+ * - Visible border that warms on hover
18
+ * - Subtle gradient background
19
+ *
20
+ * 3. VARIANTS
21
+ * - Raised: default with layered depth
22
+ * - Sunlit: featured with warm gradient
23
+ * - Flat: border-only, minimal shadow
24
+ *
25
+ * @element oh-card
26
+ */
27
+ import { OhElement } from "./base.js";
28
+ export type CardVariant = "raised" | "sunlit" | "flat";
29
+ export type CardPadding = "none" | "sm" | "md" | "lg";
30
+ export declare class OhCard extends OhElement {
31
+ static styles: import("lit").CSSResult[];
32
+ variant: CardVariant;
33
+ interactive: boolean;
34
+ padding: CardPadding;
35
+ private _handleClick;
36
+ private _handleKeyDown;
37
+ render(): import("lit").TemplateResult<1>;
38
+ }
39
+ declare global {
40
+ interface HTMLElementTagNameMap {
41
+ "oh-card": OhCard;
42
+ }
43
+ }
44
+ //# sourceMappingURL=oh-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-card.d.ts","sourceRoot":"","sources":["../src/oh-card.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtD,qBACa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,4BAiPpB;IAGF,OAAO,EAAE,WAAW,CAAY;IAGhC,WAAW,UAAS;IAGpB,OAAO,EAAE,WAAW,CAAQ;IAE5B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAOtB,MAAM;CA+BP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}