ranui 0.2.0-alpha.2 → 0.2.0-alpha.4

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 (102) hide show
  1. package/dist/builder.js +1 -1
  2. package/dist/{button-BstLjXNe.js → button-CJFSrjq_.js} +10 -10
  3. package/dist/button.js +1 -1
  4. package/dist/card-F-3fRynz.js +67 -0
  5. package/dist/card.js +1 -1
  6. package/dist/{checkbox-iHZQb-yQ.js → checkbox-BS5kNY6n.js} +9 -9
  7. package/dist/checkbox.js +1 -1
  8. package/dist/{colorpicker-CGh8pRqo.js → colorpicker-CdzUAVC5.js} +11 -11
  9. package/dist/colorpicker.js +1 -1
  10. package/dist/components/button/index.d.ts +1 -1
  11. package/dist/components/card/index.d.ts +3 -0
  12. package/dist/components/theme-switch/index.d.ts +36 -0
  13. package/dist/{dropdown-RqHMRhFE.js → dropdown-BYS1Trdu.js} +9 -9
  14. package/dist/dropdown.js +1 -1
  15. package/dist/fonts/Geist-Variable.woff2 +0 -0
  16. package/dist/fonts/GeistMono-Variable.woff2 +0 -0
  17. package/dist/fonts/OFL-LICENSE.txt +92 -0
  18. package/dist/fonts/fonts.css +26 -0
  19. package/dist/{form-05Lxxl3D.js → form-BsB5JhS4.js} +9 -9
  20. package/dist/form.js +1 -1
  21. package/dist/{icon-Blm7AbyY.js → icon-pfolda2m.js} +3 -3
  22. package/dist/icon.js +1 -1
  23. package/dist/iife/button.iife.js +1 -1
  24. package/dist/iife/card.iife.js +1 -1
  25. package/dist/iife/checkbox.iife.js +1 -1
  26. package/dist/iife/colorpicker.iife.js +2 -2
  27. package/dist/iife/dropdown.iife.js +1 -1
  28. package/dist/iife/form.iife.js +1 -1
  29. package/dist/iife/icon.iife.js +1 -1
  30. package/dist/iife/image.iife.js +1 -1
  31. package/dist/iife/input.iife.js +1 -1
  32. package/dist/iife/link.iife.js +1 -1
  33. package/dist/iife/loading.iife.js +1 -1
  34. package/dist/iife/math.iife.js +14 -14
  35. package/dist/iife/message.iife.js +1 -1
  36. package/dist/iife/modal.iife.js +1 -1
  37. package/dist/iife/player.iife.js +9 -9
  38. package/dist/iife/popover.iife.js +1 -1
  39. package/dist/iife/progress.iife.js +1 -1
  40. package/dist/iife/radar.iife.js +1 -1
  41. package/dist/iife/route.iife.js +1 -1
  42. package/dist/iife/router.iife.js +1 -1
  43. package/dist/iife/scratch.iife.js +1 -1
  44. package/dist/iife/section.iife.js +1 -1
  45. package/dist/iife/select.iife.js +2 -2
  46. package/dist/iife/skeleton.iife.js +1 -1
  47. package/dist/iife/tab.iife.js +1 -1
  48. package/dist/iife/tabpane.iife.js +1 -1
  49. package/dist/iife/theme-switch.iife.js +1 -0
  50. package/dist/{image-DKm6z7YQ.js → image-BXpKQ9sU.js} +9 -9
  51. package/dist/image.js +1 -1
  52. package/dist/index.cjs +23 -23
  53. package/dist/index.d.ts +4 -0
  54. package/dist/index.iife.js +67 -78
  55. package/dist/index.js +73 -72
  56. package/dist/{input-Dskw1bAl.js → input-BM6e_LQr.js} +13 -13
  57. package/dist/input.js +1 -1
  58. package/dist/{link-BW-gvrpN.js → link-DURZzd7u.js} +7 -7
  59. package/dist/link.js +1 -1
  60. package/dist/{loading-C4QUpm70.js → loading-Bd-gF1AH.js} +24 -24
  61. package/dist/loading.js +1 -1
  62. package/dist/{math-Dv4nXSoI.js → math-IjzOAwnA.js} +7 -7
  63. package/dist/math.js +1 -1
  64. package/dist/{message-De5e1txT.js → message-CLpuP8HY.js} +8 -8
  65. package/dist/message.js +1 -1
  66. package/dist/{modal-DruDj3AB.js → modal-DOTpABRe.js} +7 -7
  67. package/dist/modal.js +1 -1
  68. package/dist/{player-CqTAmg_E.js → player-C2pB5L2N.js} +7 -7
  69. package/dist/player.js +1 -1
  70. package/dist/{popover-BY32HNMl.js → popover-DRUQjdPs.js} +10 -10
  71. package/dist/popover.js +1 -1
  72. package/dist/{progress-gZo0knzu.js → progress-BIEXYYd2.js} +6 -6
  73. package/dist/progress.js +1 -1
  74. package/dist/{radar-19P5Mtld.js → radar-DAF95_Mj.js} +9 -9
  75. package/dist/radar.js +1 -1
  76. package/dist/ranui.css +1 -1
  77. package/dist/{route-BY_E6-2C.js → route-MQZpn2BP.js} +14 -14
  78. package/dist/route.js +1 -1
  79. package/dist/{router-BDcv4F-2.js → router-B9rCrWXm.js} +5 -5
  80. package/dist/router.js +1 -1
  81. package/dist/{scratch-Dbd9G6Q6.js → scratch-QlPyy1f4.js} +1 -1
  82. package/dist/scratch.js +1 -1
  83. package/dist/{section-CNTvgdQ-.js → section-D0qMm9KM.js} +8 -8
  84. package/dist/section.js +1 -1
  85. package/dist/{select-BVdUtQX5.js → select-BSeCT9tF.js} +13 -13
  86. package/dist/select.js +1 -1
  87. package/dist/{signal-XHfNsQNW.js → signal-CSSZxlK5.js} +1 -1
  88. package/dist/{skeleton-BAdJ6vyA.js → skeleton-CFqQmKyt.js} +8 -8
  89. package/dist/skeleton.js +1 -1
  90. package/dist/{tab-DH2owP2V.js → tab-CqFrgo2v.js} +5 -5
  91. package/dist/tab.js +1 -1
  92. package/dist/{tabpane-B_M-Jokw.js → tabpane-B-m3xwqu.js} +7 -7
  93. package/dist/tabpane.js +1 -1
  94. package/dist/test/unit/theme-switch.contract.test.d.ts +1 -0
  95. package/dist/theme-switch-B8K9y2RL.js +170 -0
  96. package/dist/theme-switch.js +5 -0
  97. package/dist/{utils-D4pPF77E.js → utils-DBfrRFoE.js} +116 -198
  98. package/docs/COMPONENTS.md +21 -5
  99. package/docs/DESIGN.md +24 -19
  100. package/docs/style-tokens-public.md +55 -8
  101. package/package.json +16 -10
  102. package/dist/card-DQUJoDUQ.js +0 -60
@@ -1,5 +1,5 @@
1
1
  import "./ssr-DSGwPtEd.js";
2
- var O = class {
2
+ var R = class {
3
3
  _events = /* @__PURE__ */ new Map();
4
4
  tap = (e, t) => {
5
5
  this._events.get(e) && e !== /* @__PURE__ */ Symbol.for("NEW_LISTENER") && this.call(/* @__PURE__ */ Symbol.for("NEW_LISTENER"), e);
@@ -16,8 +16,8 @@ var O = class {
16
16
  callSync = async (e, ...t) => {
17
17
  const r = this._events.get(e) || /* @__PURE__ */ new Set();
18
18
  for (const a of r) {
19
- const { callback: o } = a;
20
- await o(...t);
19
+ const { callback: s } = a;
20
+ await s(...t);
21
21
  }
22
22
  return this;
23
23
  };
@@ -34,8 +34,8 @@ var O = class {
34
34
  const { callback: a } = t;
35
35
  r = {
36
36
  name: e,
37
- callback: (...o) => {
38
- a(...o), this.off(e, r);
37
+ callback: (...s) => {
38
+ a(...s), this.off(e, r);
39
39
  },
40
40
  initialCallback: a
41
41
  };
@@ -46,49 +46,42 @@ var O = class {
46
46
  const r = [...this._events.get(e) || /* @__PURE__ */ new Set()].filter((a) => {
47
47
  if (typeof t == "function") return a.callback !== t && a.initialCallback !== t;
48
48
  {
49
- const { callback: o } = t;
50
- return a.callback !== o && a.initialCallback !== o;
49
+ const { callback: s } = t;
50
+ return a.callback !== s && a.initialCallback !== s;
51
51
  }
52
52
  });
53
53
  return this._events.set(e, new Set(r)), this;
54
54
  };
55
- };
56
- var C = (e = 8) => Math.random().toString(36).substring(2, e + 2);
57
- var H = (e = "") => {
55
+ }, y = (e = 8) => Math.random().toString(36).substring(2, e + 2), L = (e = "") => {
58
56
  if (e.length === 0) return 0;
59
57
  if (e.endsWith("%")) {
60
58
  const t = Number(e.replace("%", ""));
61
59
  return t > 1 ? t / 100 : t;
62
60
  }
63
61
  return Number(e);
64
- }, $ = (e, t = 0, r = 1) => Math.min(r, Math.max(t, e));
65
- var E = (e) => typeof e == "function";
66
- function f(e) {
62
+ }, O = (e, t = 0, r = 1) => Math.min(r, Math.max(t, e)), C = (e) => typeof e == "function";
63
+ function h(e) {
67
64
  return e < 10 ? `0${e}` : e;
68
65
  }
69
- var W = (e) => {
66
+ var B = (e) => {
70
67
  if (e === 0) return "00:00";
71
68
  if (!e) return "";
72
- const t = Math.trunc(e / 3600), r = Math.trunc(e % 3600 / 60), a = f(Math.trunc(e - 3600 * t - 60 * r));
73
- return t === 0 ? `${f(r)}:${a}` : `${f(t)}:${f(r)}:${a}`;
74
- };
75
- var K = () => {
69
+ const t = Math.trunc(e / 3600), r = Math.trunc(e % 3600 / 60), a = h(Math.trunc(e - 3600 * t - 60 * r));
70
+ return t === 0 ? `${h(r)}:${a}` : `${h(t)}:${h(r)}:${a}`;
71
+ }, T = () => {
76
72
  if (typeof window < "u") {
77
73
  const e = navigator.userAgent.toLowerCase();
78
74
  return /ipad|ipod/.test(e) ? "ipad" : /android/.test(e) ? "android" : /iphone/.test(e) ? "iphone" : "pc";
79
75
  }
80
76
  return "pc";
81
- }, k = typeof window < "u";
82
- var G = () => {
83
- if (!k) return !1;
77
+ }, E = typeof window < "u", U = () => {
78
+ if (!E) return !1;
84
79
  const e = window.navigator.userAgent;
85
80
  return !!/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(e);
86
- };
87
- var V = (e) => {
81
+ }, $ = (e) => {
88
82
  const t = e.backingStorePixelRatio || e.webkitBackingStorePixelRatio || e.mozBackingStorePixelRatio || e.msBackingStorePixelRatio || e.oBackingStorePixelRatio || 1;
89
- return (k && window.devicePixelRatio || 1) / t;
90
- };
91
- var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
83
+ return (E && window.devicePixelRatio || 1) / t;
84
+ }, M = 12e4, A = "__ranuts_bridge__", q = "default", m = new class {
92
85
  bridges = /* @__PURE__ */ new Set();
93
86
  attachedWindow = null;
94
87
  handleMessage = (e) => {
@@ -100,7 +93,7 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
100
93
  remove(e) {
101
94
  this.bridges.delete(e), this.bridges.size === 0 && this.attachedWindow && (this.attachedWindow.removeEventListener("message", this.handleMessage), this.attachedWindow = null);
102
95
  }
103
- }(), B = class {
96
+ }(), P = class {
104
97
  targetWindow;
105
98
  targetOrigin;
106
99
  messageHandlers;
@@ -108,13 +101,13 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
108
101
  channel;
109
102
  senderId;
110
103
  available;
111
- constructor(e, t = "*", r = U) {
112
- this.targetOrigin = t, this.channel = r, this.senderId = C(12), this.messageHandlers = /* @__PURE__ */ new Map(), this.pendingRequests = /* @__PURE__ */ new Map(), this.available = typeof window < "u", this.available ? (this.targetWindow = e ?? window, S.add(this)) : this.targetWindow = void 0;
104
+ constructor(e, t = "*", r = q) {
105
+ this.targetOrigin = t, this.channel = r, this.senderId = y(12), this.messageHandlers = /* @__PURE__ */ new Map(), this.pendingRequests = /* @__PURE__ */ new Map(), this.available = typeof window < "u", this.available ? (this.targetWindow = e ?? window, m.add(this)) : this.targetWindow = void 0;
113
106
  }
114
107
  post(e, t) {
115
108
  const r = {
116
109
  ...t,
117
- __bridge: L,
110
+ __bridge: A,
118
111
  channel: this.channel,
119
112
  senderId: this.senderId
120
113
  };
@@ -124,28 +117,28 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
124
117
  if (!this.available || this.targetOrigin !== "*" && e.origin !== this.targetOrigin || e.source && e.source !== this.targetWindow) return;
125
118
  const t = e.data;
126
119
  if (!t || typeof t != "object" || t.__bridge !== "__ranuts_bridge__" || (t.channel ?? "default") !== this.channel) return;
127
- const { type: r, payload: a, id: o, isResponse: s, isError: u, senderId: c } = t;
128
- if (s && o) {
129
- const p = this.pendingRequests.get(o);
130
- p && (u ? p.reject(new Error(typeof a == "string" ? a : "Bridge request failed")) : p.resolve(a), this.pendingRequests.delete(o));
120
+ const { type: r, payload: a, id: s, isResponse: o, isError: w, senderId: d } = t;
121
+ if (o && s) {
122
+ const c = this.pendingRequests.get(s);
123
+ c && (w ? c.reject(new Error(typeof a == "string" ? a : "Bridge request failed")) : c.resolve(a), this.pendingRequests.delete(s));
131
124
  return;
132
125
  }
133
- if (c && c === this.senderId || typeof r != "string" || !this.messageHandlers.has(r)) return;
134
- const b = this.messageHandlers.get(r);
135
- if (E(b)) {
136
- const p = e.source ?? this.targetWindow;
137
- Promise.resolve(b(a)).then((l) => {
138
- o && this.post(p, {
126
+ if (d && d === this.senderId || typeof r != "string" || !this.messageHandlers.has(r)) return;
127
+ const v = this.messageHandlers.get(r);
128
+ if (C(v)) {
129
+ const c = e.source ?? this.targetWindow;
130
+ Promise.resolve(v(a)).then((l) => {
131
+ s && this.post(c, {
139
132
  type: r,
140
133
  payload: l,
141
- id: o,
134
+ id: s,
142
135
  isResponse: !0
143
136
  });
144
137
  }).catch((l) => {
145
- o && this.post(p, {
138
+ s && this.post(c, {
146
139
  type: r,
147
140
  payload: l instanceof Error ? l.message : String(l),
148
- id: o,
141
+ id: s,
149
142
  isResponse: !0,
150
143
  isError: !0
151
144
  });
@@ -160,18 +153,18 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
160
153
  };
161
154
  send = async (e, t) => {
162
155
  if (!this.available) return Promise.reject(/* @__PURE__ */ new Error("PostMessageBridge is unavailable outside a browser environment"));
163
- const r = C(10);
164
- return new Promise((a, o) => {
165
- const s = setTimeout(() => {
166
- this.pendingRequests.has(r) && (this.pendingRequests.delete(r), o(/* @__PURE__ */ new Error("Request timeout")));
167
- }, A), u = (c) => {
168
- clearTimeout(s), o(c);
156
+ const r = y(10);
157
+ return new Promise((a, s) => {
158
+ const o = setTimeout(() => {
159
+ this.pendingRequests.has(r) && (this.pendingRequests.delete(r), s(/* @__PURE__ */ new Error("Request timeout")));
160
+ }, M), w = (d) => {
161
+ clearTimeout(o), s(d);
169
162
  };
170
163
  this.pendingRequests.set(r, {
171
- resolve: (c) => {
172
- clearTimeout(s), a(c);
164
+ resolve: (d) => {
165
+ clearTimeout(o), a(d);
173
166
  },
174
- reject: u
167
+ reject: w
175
168
  });
176
169
  try {
177
170
  this.post(this.targetWindow, {
@@ -179,8 +172,8 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
179
172
  payload: t,
180
173
  id: r
181
174
  });
182
- } catch (c) {
183
- this.pendingRequests.delete(r), u(c instanceof Error ? c : /* @__PURE__ */ new Error("Failed to post message"));
175
+ } catch (d) {
176
+ this.pendingRequests.delete(r), w(d instanceof Error ? d : /* @__PURE__ */ new Error("Failed to post message"));
184
177
  }
185
178
  });
186
179
  };
@@ -194,23 +187,23 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
194
187
  }
195
188
  };
196
189
  destroy = () => {
197
- S.remove(this), this.messageHandlers.clear(), this.pendingRequests.forEach((e) => {
190
+ m.remove(this), this.messageHandlers.clear(), this.pendingRequests.forEach((e) => {
198
191
  e.reject(/* @__PURE__ */ new Error("Bridge destroyed"));
199
192
  }), this.pendingRequests.clear();
200
193
  };
201
- }, I = class d {
194
+ }, _ = class u {
202
195
  static instance;
203
196
  bridges = /* @__PURE__ */ new Map();
204
197
  constructor() {
205
198
  }
206
199
  static getInstance() {
207
- return d.instance || (d.instance = new d()), d.instance;
200
+ return u.instance || (u.instance = new u()), u.instance;
208
201
  }
209
- connectClient = ({ id: t, targetOrigin: r, targetWindow: a, channel: o }) => {
210
- const s = new B(a, r, o);
211
- if (t || (t = C(10)), this.bridges.has(t)) throw new Error(`Bridge ${t} already exists`);
212
- return this.bridges.set(t, s), {
213
- bridge: s,
202
+ connectClient = ({ id: t, targetOrigin: r, targetWindow: a, channel: s }) => {
203
+ const o = new P(a, r, s);
204
+ if (t || (t = y(10)), this.bridges.has(t)) throw new Error(`Bridge ${t} already exists`);
205
+ return this.bridges.set(t, o), {
206
+ bridge: o,
214
207
  id: t
215
208
  };
216
209
  };
@@ -230,12 +223,10 @@ var A = 12e4, L = "__ranuts_bridge__", U = "default", S = new class {
230
223
  });
231
224
  };
232
225
  sendTo = (t, r, a) => {
233
- const o = this.getClient(t);
234
- return o ? o.send(r, a) : Promise.reject(/* @__PURE__ */ new Error(`Bridge ${t} not found`));
226
+ const s = this.getClient(t);
227
+ return s ? s.send(r, a) : Promise.reject(/* @__PURE__ */ new Error(`Bridge ${t} not found`));
235
228
  };
236
- }, Y = I.getInstance();
237
- var J = new O();
238
- var i = [
229
+ }, F = _.getInstance(), H = new R(), i = [
239
230
  1116352408,
240
231
  1899447441,
241
232
  3049323471,
@@ -300,15 +291,13 @@ var i = [
300
291
  2756734187,
301
292
  3204031479,
302
293
  3329325298
303
- ];
304
- var n = class {
294
+ ], n = class {
305
295
  highOrder;
306
296
  lowOrder;
307
297
  constructor(e, t) {
308
298
  this.highOrder = e, this.lowOrder = t;
309
299
  }
310
- };
311
- var X = [
300
+ }, x = [
312
301
  new n(i[0], 3609767458),
313
302
  new n(i[1], 602891725),
314
303
  new n(i[2], 3964484399),
@@ -389,8 +378,7 @@ var X = [
389
378
  new n(1501505948, 4234509866),
390
379
  new n(1607167915, 987167468),
391
380
  new n(1816402316, 1246189591)
392
- ];
393
- var Z = [
381
+ ], D = [
394
382
  new n(0, 1),
395
383
  new n(0, 32898),
396
384
  new n(2147483648, 32906),
@@ -415,35 +403,32 @@ var Z = [
415
403
  new n(2147483648, 32896),
416
404
  new n(0, 2147483649),
417
405
  new n(2147483648, 2147516424)
418
- ];
419
- var Q = (e, t = 500) => {
406
+ ], j = (e, t = 500) => {
420
407
  let r;
421
408
  return (...a) => {
422
409
  clearTimeout(r), r = setTimeout(() => {
423
410
  e.apply(void 0, a);
424
411
  }, t);
425
412
  };
426
- }, e0 = (e, t) => {
413
+ }, G = (e, t) => {
427
414
  if (typeof document > "u") return;
428
415
  const r = e.classList;
429
416
  r.contains(t) || r.add(t);
430
- }, t0 = (e, t) => {
417
+ }, z = (e, t) => {
431
418
  if (typeof document > "u") return;
432
419
  const r = e.classList;
433
420
  r.contains(t) && r.remove(t);
434
- };
435
- var r0 = () => {
421
+ }, V = () => {
436
422
  let e = 0, t = null;
437
423
  return function(r, a = 300) {
438
- return function(...o) {
439
- const s = Date.now();
440
- s - e >= a ? (t != null && (clearTimeout(t), t = null), e = s, r.apply(this, o)) : t ??= window.setTimeout(() => {
441
- e = Date.now(), r.apply(this, o), t = null;
442
- }, a - (s - e));
424
+ return function(...s) {
425
+ const o = Date.now();
426
+ o - e >= a ? (t != null && (clearTimeout(t), t = null), e = o, r.apply(this, s)) : t ??= window.setTimeout(() => {
427
+ e = Date.now(), r.apply(this, s), t = null;
428
+ }, a - (o - e));
443
429
  };
444
430
  };
445
- };
446
- var w = /* @__PURE__ */ new Map([
431
+ }, g = /* @__PURE__ */ new Map([
447
432
  [100, "Continue"],
448
433
  [101, "Switching Protocols"],
449
434
  [102, "Processing"],
@@ -507,18 +492,18 @@ var w = /* @__PURE__ */ new Map([
507
492
  [509, "Bandwidth Limit Exceeded"],
508
493
  [510, "Not Extended"],
509
494
  [511, "Network Authentication Required"]
510
- ]), n0 = {
511
- message: w,
495
+ ]), K = {
496
+ message: g,
512
497
  code: (function(e) {
513
498
  const t = /* @__PURE__ */ new Map();
514
499
  for (const [r, a] of e) t.set(a.toLowerCase(), r);
515
500
  return t;
516
- })(w),
501
+ })(g),
517
502
  codes: (function(e) {
518
503
  const t = [];
519
504
  for (const [r, a] of e) t.push(r);
520
505
  return t;
521
- })(w),
506
+ })(g),
522
507
  redirect: {
523
508
  300: !0,
524
509
  301: !0,
@@ -538,22 +523,22 @@ var w = /* @__PURE__ */ new Map([
538
523
  503: !0,
539
524
  504: !0
540
525
  }
541
- }, R = [
526
+ }, k = [
542
527
  !1,
543
528
  "false",
544
529
  null,
545
530
  void 0
546
- ], i0 = (e) => {
531
+ ], X = (e) => {
547
532
  const t = e.hasAttribute("disabled"), r = e.getAttribute("disabled");
548
- return !!(t && !R.includes(r));
549
- }, y = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), F = (e, t) => {
533
+ return !!(t && !k.includes(r));
534
+ }, f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), N = (e, t) => {
550
535
  if (!(typeof document > "u") && t) {
551
536
  if (typeof CSSStyleSheet < "u") try {
552
- if (!y.has(t)) {
537
+ if (!f.has(t)) {
553
538
  const a = new CSSStyleSheet();
554
- a.replaceSync(t), y.set(t, a);
539
+ a.replaceSync(t), f.set(t, a);
555
540
  }
556
- const r = y.get(t);
541
+ const r = f.get(t);
557
542
  e.adoptedStyleSheets.includes(r) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, r]);
558
543
  return;
559
544
  } catch {
@@ -563,14 +548,14 @@ var w = /* @__PURE__ */ new Map([
563
548
  r.setAttribute("data-ranui", ""), r.textContent = t, e.appendChild(r);
564
549
  }
565
550
  }
566
- }, D = (e, t) => {
551
+ }, W = (e, t) => {
567
552
  if (!(typeof document > "u") && t) {
568
553
  if (typeof CSSStyleSheet < "u") try {
569
- if (!x.has(t)) {
554
+ if (!p.has(t)) {
570
555
  const a = new CSSStyleSheet();
571
- a.replaceSync(t), x.set(t, a);
556
+ a.replaceSync(t), p.set(t, a);
572
557
  }
573
- const r = x.get(t);
558
+ const r = p.get(t);
574
559
  e.adoptedStyleSheets.includes(r) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, r]);
575
560
  return;
576
561
  } catch {
@@ -580,110 +565,43 @@ var w = /* @__PURE__ */ new Map([
580
565
  r.setAttribute("data-ranui-sheet", ""), r.textContent = t, e.appendChild(r);
581
566
  }
582
567
  }
583
- }, _ = /* @__PURE__ */ new WeakMap(), M = "@media (prefers-reduced-motion: reduce){*,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}}", a0 = (e, t = "", r = { mode: "closed" }) => {
584
- const a = e.shadowRoot || _.get(e) || e.attachShadow(r);
585
- return _.set(e, a), F(a, t ? `${t}
586
- ${M}` : M), a;
587
- }, o0 = (e, t, r) => {
568
+ }, b = /* @__PURE__ */ new WeakMap(), S = "@media (prefers-reduced-motion: reduce){*,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}}", Y = (e, t = "", r = { mode: "closed" }) => {
569
+ const a = e.shadowRoot || b.get(e) || e.attachShadow(r);
570
+ return b.set(e, a), N(a, t ? `${t}
571
+ ${S}` : S), a;
572
+ }, J = (e, t, r) => {
588
573
  const a = e.querySelector(t);
589
574
  if (a) return a;
590
- const o = r();
591
- return e.appendChild(o), o;
592
- }, s0 = (e, t, r = "") => e.getAttribute(t) ?? r, c0 = (e, t, r, a = {}) => {
575
+ const s = r();
576
+ return e.appendChild(s), s;
577
+ }, Q = (e, t, r = "") => e.getAttribute(t) ?? r, Z = (e, t, r, a = {}) => {
593
578
  if (a.removeEmpty && !r) {
594
579
  e.removeAttribute(t);
595
580
  return;
596
581
  }
597
582
  e.setAttribute(t, r ?? "");
598
- }, p0 = (e, t, r, a, o) => {
599
- if (r !== "sheet" || a === o) return;
600
- const s = e.getAttribute("sheet") || "";
601
- s && D(t, s);
602
- }, g = "ran-theme", h = null, m = null, v = (e) => {
603
- if (e && "style" in e) return e;
604
- if (e && "documentElement" in e) return e.documentElement;
605
- if (!(typeof document > "u"))
606
- return document.documentElement;
607
- }, T = (e) => {
608
- const t = typeof window < "u" && window.matchMedia("(prefers-color-scheme: dark)").matches;
609
- e.setAttribute("data-ran-theme", t ? "dark" : "light"), e.setAttribute("theme", t ? "dark" : "light");
610
- }, P = () => {
611
- h && m && (h.removeEventListener("change", m), h = null, m = null);
612
- }, N = (e, t) => {
613
- const r = v(t);
614
- if (r) {
615
- if (P(), e === "system") {
616
- if (typeof window > "u") return;
617
- T(r), h = window.matchMedia("(prefers-color-scheme: dark)"), m = () => T(r), h.addEventListener("change", m);
618
- try {
619
- localStorage.setItem(g, "system");
620
- } catch {
621
- }
622
- return;
623
- }
624
- r.setAttribute("data-ran-theme", e), r.setAttribute("theme", e);
625
- try {
626
- localStorage.setItem(g, e);
627
- } catch {
628
- }
629
- }
630
- }, l0 = (e) => {
631
- const t = v(e);
632
- if (!t) return "";
633
- const r = t.getAttribute("data-ran-theme") || t.getAttribute("theme") || "";
634
- if (r === "light" || r === "dark") {
635
- try {
636
- if (localStorage.getItem(g) === "system") return "system";
637
- } catch {
638
- }
639
- return r;
640
- }
641
- return "";
642
- }, z = (e, t, r) => {
643
- const a = v(r);
644
- a && a.style.setProperty(e, String(t));
645
- }, q = (e, t) => {
646
- const r = v(t);
647
- r && r.style.removeProperty(e);
648
- }, d0 = (e, t) => {
649
- Object.entries(e).forEach(([r, a]) => {
650
- if (a == null) {
651
- q(r, t);
652
- return;
653
- }
654
- z(r, a, t);
655
- });
656
- }, h0 = (e) => {
657
- if (!(typeof localStorage > "u"))
658
- try {
659
- const t = localStorage.getItem(g);
660
- (t === "light" || t === "dark" || t === "system") && N(t, e);
661
- } catch {
662
- }
583
+ }, ee = (e, t, r, a, s) => {
584
+ if (r !== "sheet" || a === s) return;
585
+ const o = e.getAttribute("sheet") || "";
586
+ o && W(t, o);
663
587
  };
664
588
  export {
665
- K as C,
666
- r0 as S,
667
- V as _,
668
- z as a,
669
- W as b,
670
- a0 as c,
671
- p0 as d,
672
- R as f,
673
- G as g,
674
- Q as h,
675
- N as i,
676
- s0 as l,
677
- e0 as m,
678
- l0 as n,
679
- d0 as o,
680
- i0 as p,
681
- h0 as r,
682
- o0 as s,
683
- q as t,
684
- c0 as u,
685
- t0 as v,
686
- O as w,
687
- $ as x,
688
- H as y
589
+ T as _,
590
+ ee as a,
591
+ G as c,
592
+ $ as d,
593
+ z as f,
594
+ V as g,
595
+ O as h,
596
+ Z as i,
597
+ j as l,
598
+ B as m,
599
+ Y as n,
600
+ k as o,
601
+ L as p,
602
+ Q as r,
603
+ X as s,
604
+ J as t,
605
+ U as u,
606
+ R as v
689
607
  };
@@ -6,9 +6,9 @@ shape), slots, and `::part()` names — extracted from source. For CSS variables
6
6
  (theming tokens) see [style-tokens-public.md](./style-tokens-public.md); for
7
7
  design rules see [DESIGN.md](./DESIGN.md).
8
8
 
9
- Generated at: 2026-07-05T13:14:26.449Z
9
+ Generated at: 2026-07-11T05:42:36.629Z
10
10
 
11
- 29 custom elements.
11
+ 30 custom elements.
12
12
 
13
13
  ## `<r-button>`
14
14
 
@@ -21,7 +21,7 @@ Source: `components/button/index.ts`
21
21
  - `icon: string`
22
22
  - `iconSize: string`
23
23
  - `sheet: string`
24
- - `type: string` — Visual variant: `''` (default) | `'primary'` | `'warning'` | `'text'`. Drives the `:host([type=...])` styles.
24
+ - `type: string` — Visual variant: `''` (default) | `'primary'` | `'contrast'` | `'warning'` | `'text'`. Drives the `:host([type=...])` styles.
25
25
  - **Events**: —
26
26
  - **Slots**: `default`
27
27
  - **Parts**: `button`, `content`
@@ -30,8 +30,12 @@ Source: `components/button/index.ts`
30
30
 
31
31
  Source: `components/card/index.ts`
32
32
 
33
- - **Attributes**: `description: string`, `sheet: string`, `title: string`
34
- - **Properties**: `description: string`, `sheet: string`, `title: string`
33
+ - **Attributes**: `description: string`, `hoverable: boolean`, `sheet: string`, `title: string`
34
+ - **Properties**:
35
+ - `description: string`
36
+ - `hoverable: boolean` — Interactive card (Geist): hover darkens the border and lifts to the elevated shadow tier. Purely presentational — gate it to cards that are actually clickable.
37
+ - `sheet: string`
38
+ - `title: string`
35
39
  - **Events**: —
36
40
  - **Slots**: `default`, `extra (named)`, `footer (named)`
37
41
  - **Parts**: `body`, `card`, `description`, `extra`, `footer`, `header`, `title`
@@ -322,3 +326,15 @@ Source: `components/tab/index.ts`
322
326
  - **Events**: `change` → detail `{ active }`
323
327
  - **Slots**: `default`
324
328
  - **Parts**: `content`, `content-wrap`, `header`, `indicator`, `nav`, `tabs`
329
+
330
+ ## `<r-theme-switch>`
331
+
332
+ Source: `components/theme-switch/index.ts`
333
+
334
+ - **Attributes**: `label-dark`, `label-light`, `label-system`, `sheet: string`
335
+ - **Properties**:
336
+ - `sheet: string`
337
+ - `value: RanThemeName` — `<r-theme-switch>` — a three-state (system / light / dark) segmented control
338
+ - **Events**: `change` → detail `{ theme }`
339
+ - **Slots**: —
340
+ - **Parts**: —
package/docs/DESIGN.md CHANGED
@@ -38,25 +38,27 @@ Scales: `--ran-gray-100..1000`, `--ran-gray-alpha-100..1000` (translucent, layer
38
38
 
39
39
  **Use the semantic layer, not the scale, in components:**
40
40
 
41
- | Token | Maps to | Use for |
42
- | -------------------------------------------- | ------------------------------- | ------------------- |
43
- | `--ran-color-bg` | background-100 | Page background |
44
- | `--ran-color-bg-subtle` | background-200 | Subtle page zones |
45
- | `--ran-color-bg-elevated` | bg-100 / gray-100 (dark) | Cards, surfaces |
46
- | `--ran-color-bg-muted` | gray-100 | Inset / muted fills |
47
- | `--ran-color-bg-hover` | gray-200 | Hover background |
48
- | `--ran-color-bg-active` | gray-300 | Active background |
49
- | `--ran-color-text` | gray-1000 | Primary text |
50
- | `--ran-color-text-secondary` | gray-900 | Secondary text |
51
- | `--ran-color-text-disabled` | gray-700 | Disabled text |
52
- | `--ran-color-border` | gray-400 | Default border |
53
- | `--ran-color-border-hover` | gray-500 | Hover border |
54
- | `--ran-color-border-active` | gray-600 | Active border |
55
- | `--ran-color-primary` / `-hover` / `-active` | blue-700 / 800 / 900 | Primary action |
56
- | `--ran-color-success` / `warning` / `danger` | green-700 / amber-700 / red-700 | Status |
57
- | `--ran-color-link` | blue-700 | Links |
58
-
59
- **Accent meaning:** blue = primary & links · green = success · amber = warning · red = danger/error.
41
+ | Token | Maps to | Use for |
42
+ | ------------------------------------------------ | ------------------------------- | ---------------------------- |
43
+ | `--ran-color-bg` | background-100 | Page background |
44
+ | `--ran-color-bg-subtle` | background-200 | Subtle page zones |
45
+ | `--ran-color-bg-elevated` | bg-100 / gray-100 (dark) | Cards, surfaces |
46
+ | `--ran-color-bg-muted` | gray-100 | Inset / muted fills |
47
+ | `--ran-color-bg-hover` | gray-200 | Hover background |
48
+ | `--ran-color-bg-active` | gray-300 | Active background |
49
+ | `--ran-color-text` | gray-1000 | Primary text |
50
+ | `--ran-color-text-secondary` | gray-900 | Secondary text |
51
+ | `--ran-color-text-disabled` | gray-700 | Disabled text |
52
+ | `--ran-color-border` | gray-400 | Default border |
53
+ | `--ran-color-border-hover` | gray-500 | Hover border |
54
+ | `--ran-color-border-active` | gray-600 | Active border |
55
+ | `--ran-color-primary` / `-hover` / `-active` | blue-700 / 800 / 900 | Primary action |
56
+ | `--ran-color-success` / `warning` / `danger` | green-700 / amber-700 / red-700 | Status |
57
+ | `--ran-color-link` | blue-700 | Links |
58
+ | `--ran-color-contrast-bg` / `-hover` / `-active` | gray-1000 / literal steps | Contrast (monochrome) action |
59
+ | `--ran-color-contrast-text` | background-100 | Text on contrast |
60
+
61
+ **Accent meaning:** blue = primary & links · green = success · amber = warning · red = danger/error. The **contrast** pair is the monochrome "highest-contrast" action (Geist contrast button): black-on-white in light, white-on-black in dark — use it when the primary action should carry no hue.
60
62
 
61
63
  **Light & dark:** same token name, different value. `gray-1000` is `#171717` in light and `#ededed` in dark. Components reference the _semantic name_; dark mode only redefines the base scale (one mixin), and everything re-resolves.
62
64
 
@@ -183,6 +185,9 @@ transition:
183
185
  - Theme through **CSS variables**, **`::part()`**, or the **`sheet`** attribute (escape hatch). CSS variables cross Shadow DOM; selectors do not.
184
186
  - Component tokens default to semantic tokens: `var(--ran-btn-content-background-color, var(--ran-color-primary, #006bff))`.
185
187
  - Map states to the color ladder: default → `bg`/`text`; hover → `bg-hover` / `border-hover` / `primary-hover`; active → `bg-active` / `primary-active`; disabled → `text-disabled` + reduced opacity; focus → focus ring.
188
+ - **Interactive cards opt in**: `r-card` only reacts to hover with the `hoverable` attribute (border 400 → 500 + elevated shadow). Non-interactive cards must stay inert — never add hover feedback to something that isn't clickable.
189
+ - **Theme switching UI is a component**: use `<r-theme-switch>` (system / light / dark segmented pill, wired to `setTheme`/localStorage, syncs across instances and updates `theme-color` metas) instead of hand-rolling toggles. Localize with `label` / `label-system` / `label-light` / `label-dark`.
190
+ - **Typography ships with the system**: `import 'ranui/fonts'` (or link `dist/fonts/fonts.css`) self-hosts Geist Sans + Geist Mono (variable, OFL-licensed) — the canonical faces behind `--ran-font-family` / `--ran-font-mono`. Without it the stacks fall back to system fonts.
186
191
  - See [THEME_STYLE_SYSTEM_DESIGN.md](./THEME_STYLE_SYSTEM_DESIGN.md) for the token architecture and [style-tokens-public.md](./style-tokens-public.md) for the generated per-component token list.
187
192
 
188
193
  ---