@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,56 @@
1
+ /**
2
+ * oh-input
3
+ *
4
+ * A chunky, inset input field that feels pressed into the page.
5
+ * On focus, it rises to meet you.
6
+ *
7
+ * DESIGN DECISIONS:
8
+ * ─────────────────
9
+ * 1. CHUNKY & CONFIDENT
10
+ * - Thick border (2.5px) that feels illustrative
11
+ * - Solid fill, no subtle gradients
12
+ * - 10px rounded corners (matches button)
13
+ *
14
+ * 2. INSET SHADOW (PRESSED IN)
15
+ * - Shadow offset to top-left (inset)
16
+ * - Feels pressed into the surface
17
+ * - Opposite of button's outset sticker effect
18
+ *
19
+ * 3. FOCUS RISES UP
20
+ * - Inset shadow disappears
21
+ * - Outset shadow appears (field lifts)
22
+ * - Border turns marmalade
23
+ * - Clear visual hierarchy
24
+ *
25
+ * @element oh-input
26
+ */
27
+ import { OhElement } from "./base.js";
28
+ export type InputType = "text" | "email" | "password" | "search" | "tel" | "url";
29
+ export type InputState = "default" | "hover" | "focus";
30
+ export declare class OhInput extends OhElement {
31
+ static styles: import("lit").CSSResult[];
32
+ type: InputType;
33
+ value: string;
34
+ placeholder: string;
35
+ label: string;
36
+ helperText: string;
37
+ errorText: string;
38
+ required: boolean;
39
+ /**
40
+ * Force a visual state (for documentation/Figma sync only)
41
+ * Values: 'hover' | 'focus'
42
+ */
43
+ forceState: InputState;
44
+ private _input;
45
+ private _handleInput;
46
+ private _handleChange;
47
+ focus(): void;
48
+ blur(): void;
49
+ render(): import("lit").TemplateResult<1>;
50
+ }
51
+ declare global {
52
+ interface HTMLElementTagNameMap {
53
+ "oh-input": OhInput;
54
+ }
55
+ }
56
+ //# sourceMappingURL=oh-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-input.d.ts","sourceRoot":"","sources":["../src/oh-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AACjF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvD,qBACa,OAAQ,SAAQ,SAAS;IACpC,OAAgB,MAAM,4BAoKpB;IAGF,IAAI,EAAE,SAAS,CAAU;IAGzB,KAAK,SAAM;IAGX,WAAW,SAAM;IAGjB,KAAK,SAAM;IAGX,UAAU,SAAM;IAGhB,SAAS,SAAM;IAGf,QAAQ,UAAS;IAEjB;;;OAGG;IAEH,UAAU,EAAE,UAAU,CAAa;IAGnC,OAAO,CAAC,MAAM,CAAoB;IAElC,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;IAIrB,KAAK;IAIL,IAAI;IAIJ,MAAM;CA2DP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=oh-input.figma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-input.figma.d.ts","sourceRoot":"","sources":["../src/oh-input.figma.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import figma, { html } from "@figma/code-connect/html";
2
+ /**
3
+ * Code Connect for oh-input
4
+ *
5
+ * Figma Properties:
6
+ * - Label (text): Field label
7
+ * - Value (text): Input content
8
+ * - Show Placeholder (boolean): Whether to show placeholder
9
+ * - Placeholder (text): Placeholder text when empty
10
+ * - Helper Text (text): Help text below input
11
+ * - Error Text (text): Error message (triggers error styling when set)
12
+ * - Required (boolean): Shows asterisk on label
13
+ * - State (variant): Default, Hover, Focus
14
+ */
15
+ figma.connect("https://www.figma.com/design/q9ZYrOj2w9DrTVmgQFU7bu/OHDS?node-id=1-40", {
16
+ props: {
17
+ label: figma.string("Label"),
18
+ value: figma.string("Value"),
19
+ showPlaceholder: figma.boolean("Show Placeholder"),
20
+ placeholder: figma.string("Placeholder"),
21
+ required: figma.boolean("Required"),
22
+ helperText: figma.string("Helper Text"),
23
+ errorText: figma.string("Error Text"),
24
+ },
25
+ example: (props) => html `
26
+ <oh-input
27
+ label="${props.label}"
28
+ value="${props.value}"
29
+ placeholder="${props.showPlaceholder ? props.placeholder : ""}"
30
+ ?required="${props.required}"
31
+ helper-text="${props.helperText}"
32
+ error-text="${props.errorText}"
33
+ ></oh-input>
34
+ `,
35
+ });
36
+ //# sourceMappingURL=oh-input.figma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-input.figma.js","sourceRoot":"","sources":["../src/oh-input.figma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;;;;;;;;GAYG;AAEH,KAAK,CAAC,OAAO,CACX,uEAAuE,EACvE;IACE,KAAK,EAAE;QACL,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5B,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC;QAClD,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACxC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QACnC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACvC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;KACtC;IACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAA;;iBAEX,KAAK,CAAC,KAAK;iBACX,KAAK,CAAC,KAAK;uBACL,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;qBAChD,KAAK,CAAC,QAAQ;uBACZ,KAAK,CAAC,UAAU;sBACjB,KAAK,CAAC,SAAS;;KAEhC;CACF,CACF,CAAC"}
@@ -0,0 +1,320 @@
1
+ /**
2
+ * oh-input
3
+ *
4
+ * A chunky, inset input field that feels pressed into the page.
5
+ * On focus, it rises to meet you.
6
+ *
7
+ * DESIGN DECISIONS:
8
+ * ─────────────────
9
+ * 1. CHUNKY & CONFIDENT
10
+ * - Thick border (2.5px) that feels illustrative
11
+ * - Solid fill, no subtle gradients
12
+ * - 10px rounded corners (matches button)
13
+ *
14
+ * 2. INSET SHADOW (PRESSED IN)
15
+ * - Shadow offset to top-left (inset)
16
+ * - Feels pressed into the surface
17
+ * - Opposite of button's outset sticker effect
18
+ *
19
+ * 3. FOCUS RISES UP
20
+ * - Inset shadow disappears
21
+ * - Outset shadow appears (field lifts)
22
+ * - Border turns marmalade
23
+ * - Clear visual hierarchy
24
+ *
25
+ * @element oh-input
26
+ */
27
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
28
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
29
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
30
+ 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;
31
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
32
+ };
33
+ import { html, css, nothing } from "lit";
34
+ import { customElement, property, query } from "lit/decorators.js";
35
+ import { OhElement, baseStyles } from "./base.js";
36
+ let OhInput = class OhInput extends OhElement {
37
+ constructor() {
38
+ super(...arguments);
39
+ this.type = "text";
40
+ this.value = "";
41
+ this.placeholder = "";
42
+ this.label = "";
43
+ this.helperText = "";
44
+ this.errorText = "";
45
+ this.required = false;
46
+ /**
47
+ * Force a visual state (for documentation/Figma sync only)
48
+ * Values: 'hover' | 'focus'
49
+ */
50
+ this.forceState = "default";
51
+ }
52
+ static { this.styles = [
53
+ baseStyles,
54
+ css `
55
+ /* ═══════════════════════════════════════════════════════════════
56
+ ORANGE HALO INPUT
57
+ Chunky • Inset • Rises on Focus
58
+ ═══════════════════════════════════════════════════════════════ */
59
+
60
+ :host {
61
+ display: block;
62
+ }
63
+
64
+ .input-wrapper {
65
+ display: flex;
66
+ flex-direction: column;
67
+ gap: var(--oh-spacing-2);
68
+ }
69
+
70
+ /* ─── Label: friendly and readable (16px minimum) ─── */
71
+ .label {
72
+ font-family: var(--oh-font-family-sans);
73
+ font-size: var(--oh-font-size-base);
74
+ font-weight: var(--oh-font-weight-semibold);
75
+ color: var(--oh-color-text-primary);
76
+ letter-spacing: var(--oh-font-letter-spacing-wide);
77
+ }
78
+
79
+ .label--required::after {
80
+ content: " *";
81
+ color: var(--oh-color-feedback-error);
82
+ }
83
+
84
+ /* ═══════════════════════════════════════════════════════════════
85
+ INPUT FIELD
86
+ Thick border, inset shadow, solid fill
87
+ ═══════════════════════════════════════════════════════════════ */
88
+
89
+ .input {
90
+ width: 100%;
91
+ font-family: var(--oh-font-family-sans);
92
+ color: var(--oh-color-text-primary);
93
+
94
+ /* Solid fill — no gradients */
95
+ background-color: var(--oh-color-surface-base);
96
+
97
+ /* Thick illustrative border (WCAG 3:1 compliant) */
98
+ border: var(--oh-input-base-border-width) solid var(--oh-color-border-emphasis);
99
+ border-radius: var(--oh-radius-md);
100
+
101
+ /* Inset offset shadow: pressed into page */
102
+ box-shadow: var(--oh-shadow-chunky-inset, inset 3px 3px 0 0 rgba(61, 50, 41, 0.15));
103
+
104
+ transition:
105
+ border-color var(--oh-motion-snappy) ease,
106
+ box-shadow var(--oh-motion-snappy) ease,
107
+ background-color var(--oh-motion-quick) ease;
108
+ }
109
+
110
+ .input::placeholder {
111
+ color: var(--oh-color-text-secondary); /* Readable placeholder */
112
+ }
113
+
114
+ /* ─── Hover: border warms up ─── */
115
+ .input:hover:not(:focus) {
116
+ border-color: var(--oh-color-border-hover);
117
+ }
118
+
119
+ /* ─── Focus: even inner ring on all sides (no layout shift) ─── */
120
+ .input:focus {
121
+ outline: none;
122
+ background-color: var(--oh-color-surface-white);
123
+ border-color: var(--oh-color-border-focus);
124
+
125
+ /* 2px inset ring + 2.5px border = ~4.5px total, even on all sides */
126
+ box-shadow: inset 0 0 0 2px var(--oh-color-border-focus);
127
+ }
128
+
129
+ /* ═══════════════════════════════════════════════════════════════
130
+ SIZE (single size for consistency)
131
+ ═══════════════════════════════════════════════════════════════ */
132
+
133
+ .input {
134
+ font-size: var(--oh-font-size-lg);
135
+ padding: var(--oh-spacing-3) var(--oh-spacing-4);
136
+ min-height: var(--oh-input-size-md-min-height);
137
+ }
138
+
139
+ /* ═══════════════════════════════════════════════════════════════
140
+ ERROR STATE
141
+ Warm red, chunky — still follows the same language
142
+ ═══════════════════════════════════════════════════════════════ */
143
+
144
+ .input--error {
145
+ border-color: var(--oh-color-feedback-error);
146
+ background-color: var(--oh-color-feedback-error-subtle);
147
+ box-shadow: inset 3px 3px 0 0 var(--oh-shadow-error);
148
+ }
149
+
150
+ .input--error:focus {
151
+ border-color: var(--oh-color-feedback-error);
152
+ box-shadow: inset 0 0 0 2px var(--oh-color-feedback-error);
153
+ }
154
+
155
+ /* ═══════════════════════════════════════════════════════════════
156
+ HELPER TEXT
157
+ ═══════════════════════════════════════════════════════════════ */
158
+
159
+ .helper {
160
+ font-family: var(--oh-font-family-sans);
161
+ font-size: var(--oh-font-size-base);
162
+ color: var(--oh-color-text-secondary);
163
+ letter-spacing: var(--oh-font-letter-spacing-wide);
164
+ }
165
+
166
+ .helper--error {
167
+ display: flex;
168
+ align-items: center;
169
+ gap: var(--oh-spacing-2);
170
+ color: var(--oh-color-feedback-error);
171
+ }
172
+
173
+ .error-icon {
174
+ flex-shrink: 0;
175
+ width: var(--oh-spacing-4);
176
+ height: var(--oh-spacing-4);
177
+ }
178
+
179
+ /* ═══════════════════════════════════════════════════════════════
180
+ REDUCED MOTION
181
+ ═══════════════════════════════════════════════════════════════ */
182
+
183
+ @media (prefers-reduced-motion: reduce) {
184
+ .input {
185
+ transition-duration: 0.01ms !important;
186
+ }
187
+ }
188
+
189
+ /* ═══════════════════════════════════════════════════════════════
190
+ FORCED STATES (for Figma Sync / documentation)
191
+ ═══════════════════════════════════════════════════════════════ */
192
+
193
+ /* Forced Hover */
194
+ :host([force-state="hover"]) .input {
195
+ border-color: var(--oh-color-border-hover);
196
+ }
197
+
198
+ /* Forced Focus */
199
+ :host([force-state="focus"]) .input {
200
+ background-color: var(--oh-color-surface-white);
201
+ border-color: var(--oh-color-border-focus);
202
+ box-shadow: inset 0 0 0 2px var(--oh-color-border-focus);
203
+ }
204
+
205
+ /* Error + Forced Hover */
206
+ :host([force-state="hover"]) .input--error {
207
+ border-color: var(--oh-color-feedback-error-hover, #b83a00);
208
+ }
209
+
210
+ /* Error + Forced Focus */
211
+ :host([force-state="focus"]) .input--error {
212
+ border-color: var(--oh-color-feedback-error);
213
+ box-shadow: inset 0 0 0 2px var(--oh-color-feedback-error);
214
+ }
215
+ `,
216
+ ]; }
217
+ _handleInput(event) {
218
+ const target = event.target;
219
+ this.value = target.value;
220
+ this.emit("oh-input", { value: this.value, originalEvent: event });
221
+ }
222
+ _handleChange(event) {
223
+ this.emit("oh-change", { value: this.value, originalEvent: event });
224
+ }
225
+ focus() {
226
+ this._input?.focus();
227
+ }
228
+ blur() {
229
+ this._input?.blur();
230
+ }
231
+ render() {
232
+ const hasError = !!this.errorText;
233
+ const helperContent = hasError ? this.errorText : this.helperText;
234
+ const inputClasses = this.classMap({
235
+ input: true,
236
+ "input--error": hasError,
237
+ });
238
+ return html `
239
+ <div class="input-wrapper">
240
+ ${this.label
241
+ ? html `
242
+ <label
243
+ class="label ${this.required ? "label--required" : ""}"
244
+ part="label"
245
+ for="input"
246
+ >
247
+ ${this.label}
248
+ </label>
249
+ `
250
+ : nothing}
251
+
252
+ <input
253
+ id="input"
254
+ part="input"
255
+ class=${inputClasses}
256
+ type=${this.type}
257
+ .value=${this.value}
258
+ placeholder=${this.placeholder || nothing}
259
+ ?required=${this.required}
260
+ aria-invalid=${hasError ? "true" : nothing}
261
+ aria-describedby=${helperContent ? "helper" : nothing}
262
+ @input=${this._handleInput}
263
+ @change=${this._handleChange}
264
+ />
265
+
266
+ ${helperContent
267
+ ? html `
268
+ <span
269
+ id="helper"
270
+ class="helper ${hasError ? "helper--error" : ""}"
271
+ part="helper"
272
+ role=${hasError ? "alert" : nothing}
273
+ >
274
+ ${hasError
275
+ ? html `
276
+ <svg class="error-icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
277
+ <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
278
+ </svg>
279
+ `
280
+ : nothing}
281
+ ${helperContent}
282
+ </span>
283
+ `
284
+ : nothing}
285
+ </div>
286
+ `;
287
+ }
288
+ };
289
+ __decorate([
290
+ property({ type: String })
291
+ ], OhInput.prototype, "type", void 0);
292
+ __decorate([
293
+ property({ type: String })
294
+ ], OhInput.prototype, "value", void 0);
295
+ __decorate([
296
+ property({ type: String })
297
+ ], OhInput.prototype, "placeholder", void 0);
298
+ __decorate([
299
+ property({ type: String })
300
+ ], OhInput.prototype, "label", void 0);
301
+ __decorate([
302
+ property({ type: String })
303
+ ], OhInput.prototype, "helperText", void 0);
304
+ __decorate([
305
+ property({ type: String })
306
+ ], OhInput.prototype, "errorText", void 0);
307
+ __decorate([
308
+ property({ type: Boolean, reflect: true })
309
+ ], OhInput.prototype, "required", void 0);
310
+ __decorate([
311
+ property({ type: String, reflect: true, attribute: "force-state" })
312
+ ], OhInput.prototype, "forceState", void 0);
313
+ __decorate([
314
+ query("input")
315
+ ], OhInput.prototype, "_input", void 0);
316
+ OhInput = __decorate([
317
+ customElement("oh-input")
318
+ ], OhInput);
319
+ export { OhInput };
320
+ //# sourceMappingURL=oh-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-input.js","sourceRoot":"","sources":["../src/oh-input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * oh-link
3
+ *
4
+ * A warm, playful link with retro-inspired styling.
5
+ * Two variants: inline (for body text) and standalone (for CTAs).
6
+ *
7
+ * DESIGN DECISIONS:
8
+ * ─────────────────
9
+ * 1. INLINE VARIANT
10
+ * - Dotted underline (quirky, retro feel)
11
+ * - Becomes solid on hover
12
+ * - Warm marmalade color
13
+ * - Subtle but distinctive
14
+ *
15
+ * 2. STANDALONE VARIANT
16
+ * - Bolder presence for CTAs
17
+ * - Offset shadow on hover (mini sticker effect)
18
+ * - Lift animation like other components
19
+ * - Arrow icon option
20
+ *
21
+ * 3. ACCESSIBILITY
22
+ * - Underline always visible (not color-only)
23
+ * - Clear focus state
24
+ * - Proper contrast ratios
25
+ *
26
+ * @element oh-link
27
+ */
28
+ import { OhElement } from "./base.js";
29
+ export type LinkVariant = "inline" | "standalone";
30
+ export declare class OhLink extends OhElement {
31
+ static styles: import("lit").CSSResult[];
32
+ href: string;
33
+ target: string;
34
+ rel: string;
35
+ variant: LinkVariant;
36
+ arrow: boolean;
37
+ inverse: boolean;
38
+ render(): import("lit").TemplateResult<1>;
39
+ }
40
+ declare global {
41
+ interface HTMLElementTagNameMap {
42
+ "oh-link": OhLink;
43
+ }
44
+ }
45
+ //# sourceMappingURL=oh-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oh-link.d.ts","sourceRoot":"","sources":["../src/oh-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC;AAElD,qBACa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,4BAmSpB;IAGF,IAAI,SAAM;IAGV,MAAM,SAAM;IAGZ,GAAG,SAAM;IAGT,OAAO,EAAE,WAAW,CAAY;IAGhC,KAAK,UAAS;IAGd,OAAO,UAAS;IAEhB,MAAM;CAiCP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}