@roxyapi/ui 0.2.0 → 0.2.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.
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const ROXY_UI_VERSION = "0.2.0";
1
+ export declare const ROXY_UI_VERSION = "0.2.2";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roxyapi/ui",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Web components for the RoxyAPI catalog. Drop-in charts, tables, cards, forms for astrology, tarot, numerology, biorhythm, I Ching, crystals, dreams, angel numbers, and more. One key, beautiful in 30 minutes.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -494,11 +494,11 @@ export class RoxyNatalChart extends LitElement {
494
494
  if (planets.length === 0) return nothing;
495
495
  return html`<section class="interpretations">
496
496
  <h3>Planet readings</h3>
497
- ${planets.map((p) => {
497
+ ${planets.map((p, idx) => {
498
498
  const interp = p.interpretation!;
499
499
  const glyph = PLANET_GLYPH[capitalize(p.name)] ?? '';
500
500
  const deg = formatNumber(p.degree ?? 0, 1);
501
- return html`<details class="interp-card">
501
+ return html`<details class="interp-card" name="natal-planet-readings" ?open=${idx === 0}>
502
502
  <summary>${glyph} ${p.name} <small>${p.sign ?? ''} ${deg}</small></summary>
503
503
  <div class="interp-body">
504
504
  ${interp.summary ? html`<p class="interp-summary">${interp.summary}</p>` : nothing}
@@ -143,43 +143,73 @@ export class RoxyTransitsTable extends LitElement {
143
143
  color: var(--roxy-muted, #71717a);
144
144
  }
145
145
 
146
- .nature-harmonious {
147
- color: var(--roxy-success-fg, #166534);
146
+ .overflow-scroll {
147
+ overflow-x: auto;
148
+ -webkit-overflow-scrolling: touch;
148
149
  }
149
150
 
150
- .nature-challenging {
151
- color: var(--roxy-danger-fg, #991b1b);
151
+ .aspect-card {
152
+ border: 1px solid var(--roxy-border, #e4e4e7);
153
+ border-radius: var(--roxy-radius-md, 8px);
154
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
155
+ margin-bottom: var(--roxy-space-xs, 0.25rem);
152
156
  }
153
-
154
- .nature-neutral {
157
+ .aspect-card summary {
158
+ cursor: pointer;
159
+ font-weight: 500;
160
+ color: var(--roxy-fg, #0a0a0a);
161
+ display: flex;
162
+ flex-wrap: wrap;
163
+ align-items: center;
164
+ gap: 0.5em;
165
+ }
166
+ .aspect-card summary .meta {
155
167
  color: var(--roxy-muted, #71717a);
168
+ font-weight: 400;
169
+ font-size: var(--roxy-text-xs, 0.75rem);
170
+ margin-left: auto;
171
+ font-variant-numeric: tabular-nums;
156
172
  }
157
-
158
- .arrow-cell {
159
- display: inline-flex;
160
- align-items: center;
161
- gap: 4px;
162
- white-space: nowrap;
173
+ .aspect-card .interp-body {
174
+ margin-top: var(--roxy-space-xs, 0.25rem);
175
+ color: var(--roxy-fg, #0a0a0a);
176
+ font-size: var(--roxy-text-sm, 0.875rem);
177
+ line-height: 1.45;
163
178
  }
164
-
165
- .interp {
166
- color: var(--roxy-secondary, #475569);
179
+ .aspect-card .interp-body p {
180
+ margin: 0 0 var(--roxy-space-xs, 0.25rem);
181
+ }
182
+ .interp-keywords {
183
+ display: flex;
184
+ flex-wrap: wrap;
185
+ gap: 0.25rem;
186
+ margin-top: 0.5rem;
187
+ }
188
+ .interp-keywords .kw {
189
+ padding: 1px 8px;
190
+ border-radius: 9999px;
191
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 14%, transparent);
192
+ color: var(--roxy-accent-fg, #b45309);
167
193
  font-size: var(--roxy-text-xs, 0.75rem);
168
- max-width: 22rem;
169
- white-space: nowrap;
170
- overflow: hidden;
171
- text-overflow: ellipsis;
172
194
  }
173
-
174
- @container (max-width: 600px) {
175
- .interp {
176
- display: none;
177
- }
195
+ .nature-badge {
196
+ display: inline-block;
197
+ padding: 1px 8px;
198
+ border-radius: 9999px;
199
+ font-size: var(--roxy-text-xs, 0.75rem);
200
+ font-weight: 600;
178
201
  }
179
-
180
- .overflow-scroll {
181
- overflow-x: auto;
182
- -webkit-overflow-scrolling: touch;
202
+ .nature-badge.harmonious {
203
+ background: color-mix(in srgb, var(--roxy-success, #16a34a) 12%, transparent);
204
+ color: var(--roxy-success-fg, #166534);
205
+ }
206
+ .nature-badge.challenging {
207
+ background: color-mix(in srgb, var(--roxy-danger, #dc2626) 12%, transparent);
208
+ color: var(--roxy-danger-fg, #991b1b);
209
+ }
210
+ .nature-badge.neutral {
211
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent);
212
+ color: var(--roxy-fg, #0a0a0a);
183
213
  }
184
214
  `,
185
215
  ];
@@ -224,7 +254,7 @@ export class RoxyTransitsTable extends LitElement {
224
254
  ? html`<div>
225
255
  <p class="section-label">Transit aspects</p>
226
256
  <div class="overflow-scroll">
227
- ${this.renderAspectsTable(transitAspects)}
257
+ ${this.renderAspectsList(transitAspects)}
228
258
  </div>
229
259
  </div>`
230
260
  : nothing
@@ -295,51 +325,44 @@ export class RoxyTransitsTable extends LitElement {
295
325
  </table>`;
296
326
  }
297
327
 
298
- private renderAspectsTable(
328
+ private renderAspectsList(
299
329
  aspects: NonNullable<TransitsResponse['transitAspects']>,
300
330
  ) {
301
- return html`<table class="aspects-table">
302
- <thead>
303
- <tr>
304
- <th scope="col">Transit Planet</th>
305
- <th scope="col">Natal Planet</th>
306
- <th scope="col">Type</th>
307
- <th scope="col">Orb</th>
308
- <th scope="col">Status</th>
309
- <th scope="col">Strength</th>
310
- <th scope="col" class="interp">Interpretation</th>
311
- </tr>
312
- </thead>
313
- <tbody>
314
- ${aspects.map((a) => {
315
- const tGlyph = PLANET_GLYPH[capitalize(a.transitPlanet)] ?? '';
316
- const nGlyph = PLANET_GLYPH[capitalize(a.natalPlanet)] ?? '';
317
- const natureClass = `nature-${(a.nature ?? '').toLowerCase()}`;
318
- const summary = a.interpretation?.summary ?? '';
319
- const truncated =
320
- summary.length > 120 ? `${summary.slice(0, 120)}...` : summary;
321
- return html`<tr>
322
- <td>
323
- <div class="arrow-cell">
324
- <span class="glyph" aria-hidden="true">${tGlyph}</span>
325
- ${a.transitPlanet}
326
- </div>
327
- </td>
328
- <td>
329
- <div class="arrow-cell">
330
- <span class="glyph" aria-hidden="true">${nGlyph}</span>
331
- ${a.natalPlanet}
332
- </div>
333
- </td>
334
- <td class=${natureClass}>${(a.type ?? '').toLowerCase()}</td>
335
- <td class="num">${formatNumber(a.orb, 2)}</td>
336
- <td>${a.isApplying ? 'Applying' : 'Separating'}</td>
337
- <td class="num">${formatNumber(a.strength, 1)}</td>
338
- <td class="interp" title=${summary}>${truncated}</td>
339
- </tr>`;
340
- })}
341
- </tbody>
342
- </table>`;
331
+ return html`<div role="list" aria-label="Transit aspects">
332
+ ${aspects.map((a, idx) => {
333
+ const tGlyph = PLANET_GLYPH[capitalize(a.transitPlanet)] ?? '';
334
+ const nGlyph = PLANET_GLYPH[capitalize(a.natalPlanet)] ?? '';
335
+ const nature = (a.nature ?? 'neutral').toLowerCase();
336
+ const interp = a.interpretation;
337
+ const type = (a.type ?? '').toLowerCase();
338
+ const status = a.isApplying ? 'Applying' : 'Separating';
339
+ return html`<details class="aspect-card" role="listitem" name="transit-aspects" ?open=${idx === 0}>
340
+ <summary>
341
+ <span aria-hidden="true">${tGlyph}</span>
342
+ ${a.transitPlanet}
343
+ <span class="nature-badge ${nature}">${type}</span>
344
+ <span aria-hidden="true">${nGlyph}</span>
345
+ ${a.natalPlanet}
346
+ <span class="meta">
347
+ ${status} · orb ${formatNumber(a.orb, 2)}° · strength ${formatNumber(a.strength, 1)}
348
+ </span>
349
+ </summary>
350
+ <div class="interp-body">
351
+ ${interp?.summary ? html`<p>${interp.summary}</p>` : nothing}
352
+ ${interp?.impact ? html`<p><strong>Impact:</strong> ${interp.impact}</p>` : nothing}
353
+ ${interp?.timing ? html`<p><strong>Timing:</strong> ${interp.timing}</p>` : nothing}
354
+ ${interp?.guidance ? html`<p><strong>Guidance:</strong> ${interp.guidance}</p>` : nothing}
355
+ ${
356
+ interp?.keywords?.length
357
+ ? html`<div class="interp-keywords">
358
+ ${interp.keywords.map((k) => html`<span class="kw">${k}</span>`)}
359
+ </div>`
360
+ : nothing
361
+ }
362
+ </div>
363
+ </details>`;
364
+ })}
365
+ </div>`;
343
366
  }
344
367
  }
345
368
 
@@ -2,7 +2,6 @@ import { css, html, LitElement, nothing } from 'lit';
2
2
  import { customElement, property, state } from 'lit/decorators.js';
3
3
  import type { GetYogaResponse, ListYogasResponse } from '../types/index.js';
4
4
  import { baseStyles } from '../utils/base-styles.js';
5
- import { debounce } from '../utils/debounce.js';
6
5
 
7
6
  type YogaListData =
8
7
  | ListYogasResponse
@@ -178,9 +177,9 @@ export class RoxyYogaList extends LitElement {
178
177
  @state()
179
178
  private filter = '';
180
179
 
181
- private readonly handleInput = debounce((e: Event) => {
180
+ private readonly handleInput = (e: Event) => {
182
181
  this.filter = (e.target as HTMLInputElement).value;
183
- }, 200);
182
+ };
184
183
 
185
184
  private renderQualityChip(quality: string) {
186
185
  const cls = `quality-chip quality-${quality}`;
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by scripts/sync-version.ts. Do not edit.
2
- export const ROXY_UI_VERSION = '0.2.0';
2
+ export const ROXY_UI_VERSION = '0.2.2';