@roxyapi/ui 0.0.1 → 0.1.2

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 (168) hide show
  1. package/AGENTS.md +169 -0
  2. package/LICENSE +21 -0
  3. package/README.md +198 -0
  4. package/THEMING.md +129 -0
  5. package/dist/cdn/components/biorhythm-chart.js +261 -0
  6. package/dist/cdn/components/biorhythm-chart.js.map +7 -0
  7. package/dist/cdn/components/compatibility-card.js +257 -0
  8. package/dist/cdn/components/compatibility-card.js.map +7 -0
  9. package/dist/cdn/components/dasha-timeline.js +244 -0
  10. package/dist/cdn/components/dasha-timeline.js.map +7 -0
  11. package/dist/cdn/components/data.js +258 -0
  12. package/dist/cdn/components/data.js.map +7 -0
  13. package/dist/cdn/components/dosha-card.js +254 -0
  14. package/dist/cdn/components/dosha-card.js.map +7 -0
  15. package/dist/cdn/components/endpoint-form.js +253 -0
  16. package/dist/cdn/components/endpoint-form.js.map +7 -0
  17. package/dist/cdn/components/guna-milan.js +256 -0
  18. package/dist/cdn/components/guna-milan.js.map +7 -0
  19. package/dist/cdn/components/hexagram.js +275 -0
  20. package/dist/cdn/components/hexagram.js.map +7 -0
  21. package/dist/cdn/components/horoscope-card.js +302 -0
  22. package/dist/cdn/components/horoscope-card.js.map +7 -0
  23. package/dist/cdn/components/kp-planets-table.js +224 -0
  24. package/dist/cdn/components/kp-planets-table.js.map +7 -0
  25. package/dist/cdn/components/location-search.js +267 -0
  26. package/dist/cdn/components/location-search.js.map +7 -0
  27. package/dist/cdn/components/moon-phase.js +251 -0
  28. package/dist/cdn/components/moon-phase.js.map +7 -0
  29. package/dist/cdn/components/natal-chart.js +237 -0
  30. package/dist/cdn/components/natal-chart.js.map +7 -0
  31. package/dist/cdn/components/numerology-card.js +252 -0
  32. package/dist/cdn/components/numerology-card.js.map +7 -0
  33. package/dist/cdn/components/panchang-table.js +234 -0
  34. package/dist/cdn/components/panchang-table.js.map +7 -0
  35. package/dist/cdn/components/synastry-chart.js +303 -0
  36. package/dist/cdn/components/synastry-chart.js.map +7 -0
  37. package/dist/cdn/components/tarot-card.js +260 -0
  38. package/dist/cdn/components/tarot-card.js.map +7 -0
  39. package/dist/cdn/components/tarot-spread.js +261 -0
  40. package/dist/cdn/components/tarot-spread.js.map +7 -0
  41. package/dist/cdn/components/vedic-kundli.js +189 -0
  42. package/dist/cdn/components/vedic-kundli.js.map +7 -0
  43. package/dist/cdn/roxy-ui.js +2552 -0
  44. package/dist/cdn/roxy-ui.js.map +7 -0
  45. package/dist/cdn/widgets.js +114 -0
  46. package/dist/components/biorhythm-chart.d.ts +66 -0
  47. package/dist/components/biorhythm-chart.d.ts.map +1 -0
  48. package/dist/components/biorhythm-chart.js +318 -0
  49. package/dist/components/biorhythm-chart.js.map +7 -0
  50. package/dist/components/compatibility-card.d.ts +46 -0
  51. package/dist/components/compatibility-card.d.ts.map +1 -0
  52. package/dist/components/compatibility-card.js +279 -0
  53. package/dist/components/compatibility-card.js.map +7 -0
  54. package/dist/components/dasha-timeline.d.ts +53 -0
  55. package/dist/components/dasha-timeline.d.ts.map +1 -0
  56. package/dist/components/dasha-timeline.js +269 -0
  57. package/dist/components/dasha-timeline.js.map +7 -0
  58. package/dist/components/data.d.ts +40 -0
  59. package/dist/components/data.d.ts.map +1 -0
  60. package/dist/components/data.js +339 -0
  61. package/dist/components/data.js.map +7 -0
  62. package/dist/components/dosha-card.d.ts +35 -0
  63. package/dist/components/dosha-card.d.ts.map +1 -0
  64. package/dist/components/dosha-card.js +278 -0
  65. package/dist/components/dosha-card.js.map +7 -0
  66. package/dist/components/endpoint-form.d.ts +39 -0
  67. package/dist/components/endpoint-form.d.ts.map +1 -0
  68. package/dist/components/endpoint-form.js +432 -0
  69. package/dist/components/endpoint-form.js.map +7 -0
  70. package/dist/components/guna-milan.d.ts +35 -0
  71. package/dist/components/guna-milan.d.ts.map +1 -0
  72. package/dist/components/guna-milan.js +302 -0
  73. package/dist/components/guna-milan.js.map +7 -0
  74. package/dist/components/hexagram.d.ts +47 -0
  75. package/dist/components/hexagram.d.ts.map +1 -0
  76. package/dist/components/hexagram.js +334 -0
  77. package/dist/components/hexagram.js.map +7 -0
  78. package/dist/components/horoscope-card.d.ts +38 -0
  79. package/dist/components/horoscope-card.d.ts.map +1 -0
  80. package/dist/components/horoscope-card.js +332 -0
  81. package/dist/components/horoscope-card.js.map +7 -0
  82. package/dist/components/kp-planets-table.d.ts +36 -0
  83. package/dist/components/kp-planets-table.d.ts.map +1 -0
  84. package/dist/components/kp-planets-table.js +227 -0
  85. package/dist/components/kp-planets-table.js.map +7 -0
  86. package/dist/components/location-search.d.ts +56 -0
  87. package/dist/components/location-search.d.ts.map +1 -0
  88. package/dist/components/location-search.js +401 -0
  89. package/dist/components/location-search.js.map +7 -0
  90. package/dist/components/moon-phase.d.ts +38 -0
  91. package/dist/components/moon-phase.d.ts.map +1 -0
  92. package/dist/components/moon-phase.js +284 -0
  93. package/dist/components/moon-phase.js.map +7 -0
  94. package/dist/components/natal-chart.d.ts +65 -0
  95. package/dist/components/natal-chart.d.ts.map +1 -0
  96. package/dist/components/natal-chart.js +407 -0
  97. package/dist/components/natal-chart.js.map +7 -0
  98. package/dist/components/numerology-card.d.ts +55 -0
  99. package/dist/components/numerology-card.d.ts.map +1 -0
  100. package/dist/components/numerology-card.js +274 -0
  101. package/dist/components/numerology-card.js.map +7 -0
  102. package/dist/components/panchang-table.d.ts +77 -0
  103. package/dist/components/panchang-table.d.ts.map +1 -0
  104. package/dist/components/panchang-table.js +285 -0
  105. package/dist/components/panchang-table.js.map +7 -0
  106. package/dist/components/synastry-chart.d.ts +52 -0
  107. package/dist/components/synastry-chart.d.ts.map +1 -0
  108. package/dist/components/synastry-chart.js +415 -0
  109. package/dist/components/synastry-chart.js.map +7 -0
  110. package/dist/components/tarot-card.d.ts +47 -0
  111. package/dist/components/tarot-card.d.ts.map +1 -0
  112. package/dist/components/tarot-card.js +281 -0
  113. package/dist/components/tarot-card.js.map +7 -0
  114. package/dist/components/tarot-spread.d.ts +42 -0
  115. package/dist/components/tarot-spread.d.ts.map +1 -0
  116. package/dist/components/tarot-spread.js +271 -0
  117. package/dist/components/tarot-spread.js.map +7 -0
  118. package/dist/components/vedic-kundli.d.ts +45 -0
  119. package/dist/components/vedic-kundli.d.ts.map +1 -0
  120. package/dist/components/vedic-kundli.js +325 -0
  121. package/dist/components/vedic-kundli.js.map +7 -0
  122. package/dist/index.cjs +4174 -0
  123. package/dist/index.cjs.map +7 -0
  124. package/dist/index.d.ts +30 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +4154 -0
  127. package/dist/index.js.map +7 -0
  128. package/dist/manifest.json +24 -0
  129. package/dist/styles/tokens.css +147 -0
  130. package/dist/tokens/index.d.ts +17 -0
  131. package/dist/tokens/index.d.ts.map +1 -0
  132. package/dist/utils/base-styles.d.ts +6 -0
  133. package/dist/utils/base-styles.d.ts.map +1 -0
  134. package/dist/utils/debounce.d.ts +5 -0
  135. package/dist/utils/debounce.d.ts.map +1 -0
  136. package/dist/utils/degree.d.ts +29 -0
  137. package/dist/utils/degree.d.ts.map +1 -0
  138. package/dist/utils/motion.d.ts +13 -0
  139. package/dist/utils/motion.d.ts.map +1 -0
  140. package/package.json +71 -3
  141. package/src/components/biorhythm-chart.ts +290 -0
  142. package/src/components/compatibility-card.ts +231 -0
  143. package/src/components/dasha-timeline.ts +251 -0
  144. package/src/components/data.ts +287 -0
  145. package/src/components/dosha-card.ts +215 -0
  146. package/src/components/endpoint-form.ts +433 -0
  147. package/src/components/guna-milan.ts +245 -0
  148. package/src/components/hexagram.ts +279 -0
  149. package/src/components/horoscope-card.ts +291 -0
  150. package/src/components/kp-planets-table.ts +156 -0
  151. package/src/components/location-search.ts +335 -0
  152. package/src/components/moon-phase.ts +221 -0
  153. package/src/components/natal-chart.ts +298 -0
  154. package/src/components/numerology-card.ts +243 -0
  155. package/src/components/panchang-table.ts +265 -0
  156. package/src/components/synastry-chart.ts +341 -0
  157. package/src/components/tarot-card.ts +235 -0
  158. package/src/components/tarot-spread.ts +224 -0
  159. package/src/components/vedic-kundli.ts +257 -0
  160. package/src/index.ts +61 -0
  161. package/src/styles/tokens.css +147 -0
  162. package/src/tokens/index.ts +130 -0
  163. package/src/types/index.ts +3 -0
  164. package/src/types/types.gen.ts +28526 -0
  165. package/src/utils/base-styles.ts +89 -0
  166. package/src/utils/debounce.ts +13 -0
  167. package/src/utils/degree.ts +64 -0
  168. package/src/utils/motion.ts +18 -0
@@ -0,0 +1,432 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+
12
+ // packages/ui/src/components/endpoint-form.ts
13
+ import { css as css2, html, LitElement, nothing } from "lit";
14
+ import { customElement, property, state } from "lit/decorators.js";
15
+
16
+ // packages/ui/src/utils/base-styles.ts
17
+ import { css } from "lit";
18
+ var baseStyles = css`
19
+ :host {
20
+ display: block;
21
+ container-type: inline-size;
22
+ font-family: var(
23
+ --roxy-font-sans,
24
+ system-ui,
25
+ -apple-system,
26
+ BlinkMacSystemFont,
27
+ 'Segoe UI',
28
+ Roboto,
29
+ sans-serif
30
+ );
31
+ color: var(--roxy-fg, #0a0a0a);
32
+ background: transparent;
33
+ font-size: var(--roxy-text-base, 1rem);
34
+ line-height: var(--roxy-leading-normal, 1.5);
35
+ animation: roxy-fade-in var(--roxy-motion-duration, 200ms)
36
+ var(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;
37
+ }
38
+
39
+ *,
40
+ *::before,
41
+ *::after {
42
+ box-sizing: border-box;
43
+ }
44
+
45
+ @keyframes roxy-fade-in {
46
+ from {
47
+ opacity: 0;
48
+ transform: translateY(2px);
49
+ }
50
+ to {
51
+ opacity: 1;
52
+ transform: translateY(0);
53
+ }
54
+ }
55
+
56
+ @media (prefers-reduced-motion: reduce) {
57
+ :host {
58
+ animation: none;
59
+ }
60
+ }
61
+
62
+ .roxy-skeleton {
63
+ background: linear-gradient(
64
+ 90deg,
65
+ var(--roxy-border, #e4e4e7) 0%,
66
+ color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,
67
+ var(--roxy-border, #e4e4e7) 100%
68
+ );
69
+ background-size: 200% 100%;
70
+ animation: roxy-shimmer 1.4s ease-in-out infinite;
71
+ border-radius: var(--roxy-radius-md, 8px);
72
+ }
73
+
74
+ @keyframes roxy-shimmer {
75
+ 0% {
76
+ background-position: 200% 0;
77
+ }
78
+ 100% {
79
+ background-position: -200% 0;
80
+ }
81
+ }
82
+
83
+ @media (prefers-reduced-motion: reduce) {
84
+ .roxy-skeleton {
85
+ animation: none;
86
+ }
87
+ }
88
+
89
+ .roxy-empty {
90
+ padding: var(--roxy-space-lg, 1.5rem);
91
+ color: var(--roxy-muted, #71717a);
92
+ text-align: center;
93
+ font-size: var(--roxy-text-sm, 0.875rem);
94
+ }
95
+
96
+ :host(:focus-within) .roxy-card {
97
+ outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
98
+ outline-offset: 2px;
99
+ }
100
+ `;
101
+
102
+ // packages/ui/src/components/endpoint-form.ts
103
+ var RoxyEndpointForm = class extends LitElement {
104
+ constructor() {
105
+ super(...arguments);
106
+ this.endpoint = "vedic-astrology/birth-chart";
107
+ this.method = "POST";
108
+ this.specUrl = "https://roxyapi.com/api/v2/openapi.json";
109
+ this.submitLabel = "Submit";
110
+ this.fields = [];
111
+ this.values = {};
112
+ this.hasLocation = false;
113
+ this.loaded = false;
114
+ this.onLocation = (e) => {
115
+ const detail = e.detail;
116
+ if (detail) {
117
+ this.values = {
118
+ ...this.values,
119
+ latitude: detail.latitude,
120
+ longitude: detail.longitude,
121
+ timezone: detail.timezone ?? detail.utcOffset
122
+ };
123
+ }
124
+ };
125
+ this.onSubmit = (e) => {
126
+ e.preventDefault();
127
+ const missing = this.fields.filter((f) => f.required).filter(
128
+ (f) => this.values[f.name] === void 0 || this.values[f.name] === ""
129
+ );
130
+ if (missing.length > 0) {
131
+ this.dispatchEvent(
132
+ new CustomEvent("roxy-validation-error", {
133
+ detail: { missing: missing.map((m) => m.name) },
134
+ bubbles: true,
135
+ composed: true
136
+ })
137
+ );
138
+ return;
139
+ }
140
+ this.dispatchEvent(
141
+ new CustomEvent("roxy-submit", {
142
+ detail: { endpoint: this.endpoint, values: this.values },
143
+ bubbles: true,
144
+ composed: true
145
+ })
146
+ );
147
+ };
148
+ }
149
+ connectedCallback() {
150
+ super.connectedCallback();
151
+ void this.loadSchema();
152
+ }
153
+ async loadSchema() {
154
+ try {
155
+ const res = await fetch(this.specUrl);
156
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
157
+ const spec = await res.json();
158
+ const path = `/${this.endpoint.replace(/^\//, "")}`;
159
+ const op = spec.paths?.[path]?.[this.method.toLowerCase()];
160
+ if (!op) return;
161
+ const schemas = spec.components?.schemas ?? {};
162
+ const fields = [];
163
+ let bodySchema;
164
+ if (op.requestBody) {
165
+ const ref = op.requestBody.content?.["application/json"]?.schema;
166
+ bodySchema = this.resolve(ref, schemas);
167
+ }
168
+ if (bodySchema?.properties) {
169
+ const required = new Set(bodySchema.required ?? []);
170
+ for (const [name, sub] of Object.entries(bodySchema.properties)) {
171
+ const resolved = this.resolve(sub, schemas) ?? {};
172
+ fields.push({
173
+ name,
174
+ type: this.fieldType(resolved),
175
+ required: required.has(name),
176
+ description: resolved.description,
177
+ enum: resolved.enum,
178
+ min: resolved.minimum,
179
+ max: resolved.maximum,
180
+ default: resolved.default
181
+ });
182
+ }
183
+ }
184
+ for (const param of op.parameters ?? []) {
185
+ if (param.in === "path" || param.in === "query") {
186
+ const resolved = this.resolve(param.schema, schemas) ?? {};
187
+ fields.push({
188
+ name: param.name,
189
+ type: this.fieldType(resolved),
190
+ required: !!param.required,
191
+ description: resolved.description,
192
+ enum: resolved.enum,
193
+ default: resolved.default
194
+ });
195
+ }
196
+ }
197
+ this.fields = fields;
198
+ this.hasLocation = fields.some((f) => f.name === "latitude") && fields.some((f) => f.name === "longitude") && fields.some((f) => f.name === "timezone");
199
+ const init = {};
200
+ for (const f of fields) {
201
+ if (f.default !== void 0) init[f.name] = f.default;
202
+ }
203
+ this.values = init;
204
+ this.loaded = true;
205
+ } catch (_err) {
206
+ this.loaded = true;
207
+ }
208
+ }
209
+ resolve(schema, all) {
210
+ if (!schema) return void 0;
211
+ if ("$ref" in schema && schema.$ref) {
212
+ const name = schema.$ref.split("/").pop();
213
+ return name ? all[name] : void 0;
214
+ }
215
+ return schema;
216
+ }
217
+ fieldType(s) {
218
+ if (s.enum) return "enum";
219
+ if (s.format === "date") return "date";
220
+ if (s.format === "time") return "time";
221
+ if (s.format === "date-time") return "datetime";
222
+ if (s.type === "integer" || s.type === "number") return "number";
223
+ return "text";
224
+ }
225
+ setValue(name, value) {
226
+ this.values = { ...this.values, [name]: value };
227
+ }
228
+ render() {
229
+ if (!this.loaded) {
230
+ return html`<form><div class="roxy-skeleton" style="height: 8rem"></div></form>`;
231
+ }
232
+ const renderField = (f) => {
233
+ if (this.hasLocation && (f.name === "latitude" || f.name === "longitude" || f.name === "timezone")) {
234
+ return nothing;
235
+ }
236
+ const inputId = `roxy-form-${f.name}`;
237
+ return html`<div class="field">
238
+ <label for=${inputId}>
239
+ ${humanize(f.name)}${f.required ? html`<span class="req" aria-hidden="true">*</span>` : nothing}
240
+ </label>
241
+ ${f.enum ? html`<select
242
+ id=${inputId}
243
+ ?required=${f.required}
244
+ @change=${(e) => this.setValue(f.name, e.target.value)}
245
+ >
246
+ <option value="">Choose</option>
247
+ ${f.enum.map(
248
+ (opt) => html`<option value=${opt} ?selected=${this.values[f.name] === opt}>
249
+ ${opt}
250
+ </option>`
251
+ )}
252
+ </select>` : html`<input
253
+ id=${inputId}
254
+ type=${this.htmlType(f.type)}
255
+ ?required=${f.required}
256
+ min=${f.min ?? ""}
257
+ max=${f.max ?? ""}
258
+ step=${f.type === "number" ? "any" : ""}
259
+ .value=${this.values[f.name] ?? ""}
260
+ @input=${(e) => this.setValue(
261
+ f.name,
262
+ this.coerce(f.type, e.target.value)
263
+ )}
264
+ />`}
265
+ ${f.description ? html`<small class="help">${f.description}</small>` : nothing}
266
+ </div>`;
267
+ };
268
+ return html`<form @submit=${this.onSubmit}>
269
+ <h2 class="title">${humanize(this.endpoint.split("/").pop() ?? "")}</h2>
270
+ ${this.hasLocation ? html`<div class="location-block">
271
+ <label>Birth location</label>
272
+ <roxy-location-search
273
+ @roxy-location-select=${this.onLocation}
274
+ placeholder="City of birth"
275
+ ></roxy-location-search>
276
+ <small class="help">
277
+ Required: latitude, longitude, timezone. Pick a city to autofill.
278
+ </small>
279
+ </div>` : nothing}
280
+ <div class="fields">
281
+ ${this.fields.map((f) => renderField(f))}
282
+ </div>
283
+ <button class="submit" type="submit">${this.submitLabel}</button>
284
+ </form>`;
285
+ }
286
+ htmlType(t) {
287
+ switch (t) {
288
+ case "date":
289
+ return "date";
290
+ case "time":
291
+ return "time";
292
+ case "datetime":
293
+ return "datetime-local";
294
+ case "number":
295
+ return "number";
296
+ default:
297
+ return "text";
298
+ }
299
+ }
300
+ coerce(t, v) {
301
+ if (v === "") return void 0;
302
+ if (t === "number") {
303
+ const n = Number(v);
304
+ return Number.isFinite(n) ? n : void 0;
305
+ }
306
+ return v;
307
+ }
308
+ };
309
+ RoxyEndpointForm.styles = [
310
+ baseStyles,
311
+ css2`
312
+ form {
313
+ display: grid;
314
+ gap: var(--roxy-space-md, 1rem);
315
+ background: var(--roxy-bg, #fff);
316
+ border: 1px solid var(--roxy-border, #e4e4e7);
317
+ border-radius: var(--roxy-radius-md, 8px);
318
+ padding: var(--roxy-space-lg, 1.5rem);
319
+ box-shadow: var(--roxy-shadow-sm);
320
+ }
321
+ .title {
322
+ margin: 0;
323
+ font-size: var(--roxy-text-lg, 1.125rem);
324
+ font-weight: var(--roxy-weight-bold, 600);
325
+ }
326
+ .fields {
327
+ display: grid;
328
+ grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
329
+ gap: var(--roxy-space-md, 1rem);
330
+ }
331
+ .field {
332
+ display: grid;
333
+ gap: var(--roxy-space-xs, 0.25rem);
334
+ }
335
+ label {
336
+ font-size: var(--roxy-text-sm, 0.875rem);
337
+ color: var(--roxy-secondary, #475569);
338
+ }
339
+ label .req {
340
+ color: var(--roxy-danger, #dc2626);
341
+ margin-left: 4px;
342
+ }
343
+ input,
344
+ select {
345
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
346
+ font-size: var(--roxy-text-base, 1rem);
347
+ font-family: inherit;
348
+ color: var(--roxy-fg, #0a0a0a);
349
+ background: var(--roxy-bg, #fff);
350
+ border: 1px solid var(--roxy-border, #e4e4e7);
351
+ border-radius: var(--roxy-radius-md, 8px);
352
+ }
353
+ input:focus,
354
+ select:focus {
355
+ outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
356
+ outline-offset: 2px;
357
+ border-color: var(--roxy-accent-fg, #b45309);
358
+ }
359
+ .help {
360
+ color: var(--roxy-muted, #71717a);
361
+ font-size: var(--roxy-text-xs, 0.75rem);
362
+ }
363
+ .location-block {
364
+ display: grid;
365
+ gap: var(--roxy-space-xs, 0.25rem);
366
+ grid-column: 1 / -1;
367
+ }
368
+ .coords {
369
+ display: grid;
370
+ grid-template-columns: repeat(3, 1fr);
371
+ gap: var(--roxy-space-sm, 0.5rem);
372
+ }
373
+ .coords input {
374
+ font-size: var(--roxy-text-sm, 0.875rem);
375
+ }
376
+ button.submit {
377
+ justify-self: start;
378
+ background: var(--roxy-accent-fg, #b45309);
379
+ color: #fff;
380
+ border: 0;
381
+ border-radius: var(--roxy-radius-md, 8px);
382
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-lg, 1.5rem);
383
+ font-size: var(--roxy-text-base, 1rem);
384
+ font-weight: var(--roxy-weight-bold, 600);
385
+ cursor: pointer;
386
+ transition:
387
+ transform var(--roxy-motion-duration, 200ms)
388
+ var(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1));
389
+ }
390
+ button.submit:hover {
391
+ transform: scale(1.02);
392
+ }
393
+ button.submit:focus-visible {
394
+ outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
395
+ outline-offset: 2px;
396
+ }
397
+ `
398
+ ];
399
+ __decorateClass([
400
+ property({ type: String, attribute: "data-endpoint" })
401
+ ], RoxyEndpointForm.prototype, "endpoint", 2);
402
+ __decorateClass([
403
+ property({ type: String })
404
+ ], RoxyEndpointForm.prototype, "method", 2);
405
+ __decorateClass([
406
+ property({ type: String, attribute: "spec-url" })
407
+ ], RoxyEndpointForm.prototype, "specUrl", 2);
408
+ __decorateClass([
409
+ property({ type: String, attribute: "submit-label" })
410
+ ], RoxyEndpointForm.prototype, "submitLabel", 2);
411
+ __decorateClass([
412
+ state()
413
+ ], RoxyEndpointForm.prototype, "fields", 2);
414
+ __decorateClass([
415
+ state()
416
+ ], RoxyEndpointForm.prototype, "values", 2);
417
+ __decorateClass([
418
+ state()
419
+ ], RoxyEndpointForm.prototype, "hasLocation", 2);
420
+ __decorateClass([
421
+ state()
422
+ ], RoxyEndpointForm.prototype, "loaded", 2);
423
+ RoxyEndpointForm = __decorateClass([
424
+ customElement("roxy-endpoint-form")
425
+ ], RoxyEndpointForm);
426
+ function humanize(s) {
427
+ return s.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^\w/, (c) => c.toUpperCase());
428
+ }
429
+ export {
430
+ RoxyEndpointForm
431
+ };
432
+ //# sourceMappingURL=endpoint-form.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/endpoint-form.ts", "../../src/utils/base-styles.ts"],
4
+ "sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ninterface OpenApiSchemaRef {\n\t$ref?: string;\n}\n\ninterface OpenApiSchema extends OpenApiSchemaRef {\n\ttype?: string;\n\tformat?: string;\n\tdescription?: string;\n\tenum?: string[];\n\tdefault?: unknown;\n\tminimum?: number;\n\tmaximum?: number;\n\tproperties?: Record<string, OpenApiSchema>;\n\trequired?: string[];\n\titems?: OpenApiSchema;\n\texample?: unknown;\n}\n\ninterface FieldDef {\n\tname: string;\n\ttype: string;\n\trequired: boolean;\n\tdescription?: string;\n\tenum?: string[];\n\tmin?: number;\n\tmax?: number;\n\tdefault?: unknown;\n}\n\n/**\n * Schema-driven form. Pass `endpoint` (e.g. \"vedic-astrology/birth-chart\").\n * The form introspects the cached OpenAPI spec, slots a roxy-location-search\n * when latitude+longitude+timezone fields are present, and emits a\n * `roxy-submit` CustomEvent with the validated payload on submit. The caller\n * decides what to do (call the SDK, render a chart, navigate).\n *\n * Build-time hints (x-roxy-ui formGroups) are read by scripts/build.ts and\n * baked into a static map. At runtime the component falls back to runtime\n * fetch of /api/v2/openapi.json when no map is provided.\n */\n@customElement('roxy-endpoint-form')\nexport class RoxyEndpointForm extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\tform {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\t\t\tbox-shadow: var(--roxy-shadow-sm);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.fields {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.field {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tcolor: var(--roxy-secondary, #475569);\n\t\t\t}\n\t\t\tlabel .req {\n\t\t\t\tcolor: var(--roxy-danger, #dc2626);\n\t\t\t\tmargin-left: 4px;\n\t\t\t}\n\t\t\tinput,\n\t\t\tselect {\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-family: inherit;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t}\n\t\t\tinput:focus,\n\t\t\tselect:focus {\n\t\t\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\t\t\toutline-offset: 2px;\n\t\t\t\tborder-color: var(--roxy-accent-fg, #b45309);\n\t\t\t}\n\t\t\t.help {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t}\n\t\t\t.location-block {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t\tgrid-column: 1 / -1;\n\t\t\t}\n\t\t\t.coords {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(3, 1fr);\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t}\n\t\t\t.coords input {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\tbutton.submit {\n\t\t\t\tjustify-self: start;\n\t\t\t\tbackground: var(--roxy-accent-fg, #b45309);\n\t\t\t\tcolor: #fff;\n\t\t\t\tborder: 0;\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-lg, 1.5rem);\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tcursor: pointer;\n\t\t\t\ttransition:\n\t\t\t\t\ttransform var(--roxy-motion-duration, 200ms)\n\t\t\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1));\n\t\t\t}\n\t\t\tbutton.submit:hover {\n\t\t\t\ttransform: scale(1.02);\n\t\t\t}\n\t\t\tbutton.submit:focus-visible {\n\t\t\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\t\t\toutline-offset: 2px;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ type: String, attribute: 'data-endpoint' })\n\tendpoint = 'vedic-astrology/birth-chart';\n\n\t@property({ type: String })\n\tmethod: 'GET' | 'POST' = 'POST';\n\n\t@property({ type: String, attribute: 'spec-url' })\n\tspecUrl = 'https://roxyapi.com/api/v2/openapi.json';\n\n\t@property({ type: String, attribute: 'submit-label' })\n\tsubmitLabel = 'Submit';\n\n\t@state()\n\tprivate fields: FieldDef[] = [];\n\n\t@state()\n\tprivate values: Record<string, unknown> = {};\n\n\t@state()\n\tprivate hasLocation = false;\n\n\t@state()\n\tprivate loaded = false;\n\n\tconnectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tvoid this.loadSchema();\n\t}\n\n\tprivate async loadSchema() {\n\t\ttry {\n\t\t\tconst res = await fetch(this.specUrl);\n\t\t\tif (!res.ok) throw new Error(`HTTP ${res.status}`);\n\t\t\tconst spec = (await res.json()) as {\n\t\t\t\tpaths?: Record<string, Record<string, unknown>>;\n\t\t\t\tcomponents?: { schemas?: Record<string, OpenApiSchema> };\n\t\t\t};\n\t\t\tconst path = `/${this.endpoint.replace(/^\\//, '')}`;\n\t\t\tconst op = spec.paths?.[path]?.[this.method.toLowerCase()] as\n\t\t\t\t| {\n\t\t\t\t\t\trequestBody?: {\n\t\t\t\t\t\t\tcontent?: Record<\n\t\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t\t{ schema?: OpenApiSchema | OpenApiSchemaRef }\n\t\t\t\t\t\t\t>;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparameters?: Array<{\n\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\tin: string;\n\t\t\t\t\t\t\trequired?: boolean;\n\t\t\t\t\t\t\tschema?: OpenApiSchema;\n\t\t\t\t\t\t}>;\n\t\t\t\t }\n\t\t\t\t| undefined;\n\t\t\tif (!op) return;\n\n\t\t\tconst schemas = spec.components?.schemas ?? {};\n\t\t\tconst fields: FieldDef[] = [];\n\t\t\tlet bodySchema: OpenApiSchema | undefined;\n\n\t\t\tif (op.requestBody) {\n\t\t\t\tconst ref = op.requestBody.content?.['application/json']?.schema;\n\t\t\t\tbodySchema = this.resolve(ref, schemas);\n\t\t\t}\n\n\t\t\tif (bodySchema?.properties) {\n\t\t\t\tconst required = new Set(bodySchema.required ?? []);\n\t\t\t\tfor (const [name, sub] of Object.entries(bodySchema.properties)) {\n\t\t\t\t\tconst resolved = this.resolve(sub, schemas) ?? {};\n\t\t\t\t\tfields.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\ttype: this.fieldType(resolved),\n\t\t\t\t\t\trequired: required.has(name),\n\t\t\t\t\t\tdescription: resolved.description,\n\t\t\t\t\t\tenum: resolved.enum,\n\t\t\t\t\t\tmin: resolved.minimum,\n\t\t\t\t\t\tmax: resolved.maximum,\n\t\t\t\t\t\tdefault: resolved.default,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const param of op.parameters ?? []) {\n\t\t\t\tif (param.in === 'path' || param.in === 'query') {\n\t\t\t\t\tconst resolved = this.resolve(param.schema, schemas) ?? {};\n\t\t\t\t\tfields.push({\n\t\t\t\t\t\tname: param.name,\n\t\t\t\t\t\ttype: this.fieldType(resolved),\n\t\t\t\t\t\trequired: !!param.required,\n\t\t\t\t\t\tdescription: resolved.description,\n\t\t\t\t\t\tenum: resolved.enum,\n\t\t\t\t\t\tdefault: resolved.default,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.fields = fields;\n\t\t\tthis.hasLocation =\n\t\t\t\tfields.some((f) => f.name === 'latitude') &&\n\t\t\t\tfields.some((f) => f.name === 'longitude') &&\n\t\t\t\tfields.some((f) => f.name === 'timezone');\n\n\t\t\t// Pre-fill defaults\n\t\t\tconst init: Record<string, unknown> = {};\n\t\t\tfor (const f of fields) {\n\t\t\t\tif (f.default !== undefined) init[f.name] = f.default;\n\t\t\t}\n\t\t\tthis.values = init;\n\t\t\tthis.loaded = true;\n\t\t} catch (_err) {\n\t\t\tthis.loaded = true;\n\t\t}\n\t}\n\n\tprivate resolve(\n\t\tschema: OpenApiSchema | OpenApiSchemaRef | undefined,\n\t\tall: Record<string, OpenApiSchema>,\n\t): OpenApiSchema | undefined {\n\t\tif (!schema) return undefined;\n\t\tif ('$ref' in schema && schema.$ref) {\n\t\t\tconst name = schema.$ref.split('/').pop();\n\t\t\treturn name ? all[name] : undefined;\n\t\t}\n\t\treturn schema as OpenApiSchema;\n\t}\n\n\tprivate fieldType(s: OpenApiSchema): string {\n\t\tif (s.enum) return 'enum';\n\t\tif (s.format === 'date') return 'date';\n\t\tif (s.format === 'time') return 'time';\n\t\tif (s.format === 'date-time') return 'datetime';\n\t\tif (s.type === 'integer' || s.type === 'number') return 'number';\n\t\treturn 'text';\n\t}\n\n\tprivate setValue(name: string, value: unknown) {\n\t\tthis.values = { ...this.values, [name]: value };\n\t}\n\n\tprivate onLocation = (e: Event) => {\n\t\tconst detail = (e as CustomEvent).detail as {\n\t\t\tlatitude?: number;\n\t\t\tlongitude?: number;\n\t\t\ttimezone?: string;\n\t\t\tutcOffset?: number;\n\t\t};\n\t\tif (detail) {\n\t\t\tthis.values = {\n\t\t\t\t...this.values,\n\t\t\t\tlatitude: detail.latitude,\n\t\t\t\tlongitude: detail.longitude,\n\t\t\t\ttimezone: detail.timezone ?? detail.utcOffset,\n\t\t\t};\n\t\t}\n\t};\n\n\tprivate onSubmit = (e: Event) => {\n\t\te.preventDefault();\n\t\tconst missing = this.fields\n\t\t\t.filter((f) => f.required)\n\t\t\t.filter(\n\t\t\t\t(f) => this.values[f.name] === undefined || this.values[f.name] === '',\n\t\t\t);\n\t\tif (missing.length > 0) {\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent('roxy-validation-error', {\n\t\t\t\t\tdetail: { missing: missing.map((m) => m.name) },\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcomposed: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('roxy-submit', {\n\t\t\t\tdetail: { endpoint: this.endpoint, values: this.values },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t);\n\t};\n\n\trender() {\n\t\tif (!this.loaded) {\n\t\t\treturn html`<form><div class=\"roxy-skeleton\" style=\"height: 8rem\"></div></form>`;\n\t\t}\n\n\t\tconst renderField = (f: FieldDef) => {\n\t\t\tif (\n\t\t\t\tthis.hasLocation &&\n\t\t\t\t(f.name === 'latitude' ||\n\t\t\t\t\tf.name === 'longitude' ||\n\t\t\t\t\tf.name === 'timezone')\n\t\t\t) {\n\t\t\t\treturn nothing;\n\t\t\t}\n\t\t\tconst inputId = `roxy-form-${f.name}`;\n\t\t\treturn html`<div class=\"field\">\n\t\t\t\t<label for=${inputId}>\n\t\t\t\t\t${humanize(f.name)}${f.required ? html`<span class=\"req\" aria-hidden=\"true\">*</span>` : nothing}\n\t\t\t\t</label>\n\t\t\t\t${\n\t\t\t\t\tf.enum\n\t\t\t\t\t\t? html`<select\n\t\t\t\t\t\t\tid=${inputId}\n\t\t\t\t\t\t\t?required=${f.required}\n\t\t\t\t\t\t\t@change=${(e: Event) => this.setValue(f.name, (e.target as HTMLSelectElement).value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<option value=\"\">Choose</option>\n\t\t\t\t\t\t\t${f.enum.map(\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\topt,\n\t\t\t\t\t\t\t\t) => html`<option value=${opt} ?selected=${this.values[f.name] === opt}>\n\t\t\t\t\t\t\t\t\t${opt}\n\t\t\t\t\t\t\t\t</option>`,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</select>`\n\t\t\t\t\t\t: html`<input\n\t\t\t\t\t\t\tid=${inputId}\n\t\t\t\t\t\t\ttype=${this.htmlType(f.type)}\n\t\t\t\t\t\t\t?required=${f.required}\n\t\t\t\t\t\t\tmin=${f.min ?? ''}\n\t\t\t\t\t\t\tmax=${f.max ?? ''}\n\t\t\t\t\t\t\tstep=${f.type === 'number' ? 'any' : ''}\n\t\t\t\t\t\t\t.value=${(this.values[f.name] ?? '') as string}\n\t\t\t\t\t\t\t@input=${(e: Event) =>\n\t\t\t\t\t\t\t\tthis.setValue(\n\t\t\t\t\t\t\t\t\tf.name,\n\t\t\t\t\t\t\t\t\tthis.coerce(f.type, (e.target as HTMLInputElement).value),\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>`\n\t\t\t\t}\n\t\t\t\t${f.description ? html`<small class=\"help\">${f.description}</small>` : nothing}\n\t\t\t</div>`;\n\t\t};\n\n\t\treturn html`<form @submit=${this.onSubmit}>\n\t\t\t<h2 class=\"title\">${humanize(this.endpoint.split('/').pop() ?? '')}</h2>\n\t\t\t${\n\t\t\t\tthis.hasLocation\n\t\t\t\t\t? html`<div class=\"location-block\">\n\t\t\t\t\t\t<label>Birth location</label>\n\t\t\t\t\t\t<roxy-location-search\n\t\t\t\t\t\t\t@roxy-location-select=${this.onLocation}\n\t\t\t\t\t\t\tplaceholder=\"City of birth\"\n\t\t\t\t\t\t></roxy-location-search>\n\t\t\t\t\t\t<small class=\"help\">\n\t\t\t\t\t\t\tRequired: latitude, longitude, timezone. Pick a city to autofill.\n\t\t\t\t\t\t</small>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t\t<div class=\"fields\">\n\t\t\t\t${this.fields.map((f) => renderField(f))}\n\t\t\t</div>\n\t\t\t<button class=\"submit\" type=\"submit\">${this.submitLabel}</button>\n\t\t</form>`;\n\t}\n\n\tprivate htmlType(t: string): string {\n\t\tswitch (t) {\n\t\t\tcase 'date':\n\t\t\t\treturn 'date';\n\t\t\tcase 'time':\n\t\t\t\treturn 'time';\n\t\t\tcase 'datetime':\n\t\t\t\treturn 'datetime-local';\n\t\t\tcase 'number':\n\t\t\t\treturn 'number';\n\t\t\tdefault:\n\t\t\t\treturn 'text';\n\t\t}\n\t}\n\n\tprivate coerce(t: string, v: string): unknown {\n\t\tif (v === '') return undefined;\n\t\tif (t === 'number') {\n\t\t\tconst n = Number(v);\n\t\t\treturn Number.isFinite(n) ? n : undefined;\n\t\t}\n\t\treturn v;\n\t}\n}\n\nfunction humanize(s: string): string {\n\treturn s\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-endpoint-form': RoxyEndpointForm;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n"],
5
+ "mappings": "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",
6
+ "names": ["css", "css"]
7
+ }
@@ -0,0 +1,35 @@
1
+ import { LitElement } from 'lit';
2
+ interface GunaCategory {
3
+ name?: string;
4
+ score?: number;
5
+ max?: number;
6
+ maxScore?: number;
7
+ description?: string;
8
+ }
9
+ interface GunaData {
10
+ total?: number;
11
+ totalScore?: number;
12
+ maxScore?: number;
13
+ percentage?: number;
14
+ isCompatible?: boolean;
15
+ recommendation?: string;
16
+ doshas?: string[];
17
+ doshaCancellations?: string[];
18
+ breakdown?: GunaCategory[];
19
+ }
20
+ /**
21
+ * 36-point Ashtakoota score card. Renders /vedic-astrology/compatibility.
22
+ */
23
+ export declare class RoxyGunaMilan extends LitElement {
24
+ static styles: import("lit").CSSResult[];
25
+ data: GunaData | null;
26
+ render(): import("lit").TemplateResult<1>;
27
+ }
28
+ export declare const GUNA_CATEGORIES: string[];
29
+ declare global {
30
+ interface HTMLElementTagNameMap {
31
+ 'roxy-guna-milan': RoxyGunaMilan;
32
+ }
33
+ }
34
+ export {};
35
+ //# sourceMappingURL=guna-milan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guna-milan.d.ts","sourceRoot":"","sources":["../../src/components/guna-milan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAIrD,UAAU,YAAY;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,QAAQ;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAaD;;GAEG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC5C,MAAM,CAAC,MAAM,4BAgGX;IAGF,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE7B,MAAM;CAsEN;AA2BD,eAAO,MAAM,eAAe,UAAsB,CAAC;AAEnD,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,iBAAiB,EAAE,aAAa,CAAC;KACjC;CACD"}