slexkit 0.3.1 → 0.3.3

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.
@@ -499,19 +499,31 @@
499
499
  function createComponentAccessor(read) {
500
500
  const subscribers = new Set;
501
501
  let current = read();
502
- const accessor = () => current;
503
- accessor.subscribe = (run) => {
504
- subscribers.add(run);
505
- run(current);
506
- const stop = createEffect(() => {
502
+ let stopEffect;
503
+ const start = () => {
504
+ if (stopEffect)
505
+ return;
506
+ stopEffect = createEffect(() => {
507
507
  current = read();
508
- for (const subscriber of subscribers)
508
+ for (const subscriber of Array.from(subscribers))
509
509
  subscriber(current);
510
510
  flushDom?.();
511
511
  });
512
+ };
513
+ const accessor = () => current;
514
+ accessor.subscribe = (run) => {
515
+ const wasIdle = subscribers.size === 0;
516
+ subscribers.add(run);
517
+ if (wasIdle)
518
+ start();
519
+ else
520
+ run(current);
512
521
  return () => {
513
522
  subscribers.delete(run);
514
- stop();
523
+ if (subscribers.size === 0) {
524
+ stopEffect?.();
525
+ stopEffect = undefined;
526
+ }
515
527
  };
516
528
  };
517
529
  return accessor;
@@ -1362,9 +1374,10 @@
1362
1374
  const renderer = getRenderer(type);
1363
1375
  if (!renderer)
1364
1376
  return;
1365
- const forWrapper = (container.ownerDocument || document).createElement("div");
1366
- forWrapper.className = "slexkit-for-wrapper";
1367
- container.appendChild(forWrapper);
1377
+ const doc = container.ownerDocument || document;
1378
+ const startAnchor = doc.createComment(`slexkit-for:${fullKey}:start`);
1379
+ const endAnchor = doc.createComment(`slexkit-for:${fullKey}:end`);
1380
+ container.append(startAnchor, endAnchor);
1368
1381
  const evalCtx = buildComponentEvalContext(g, components, componentTypes, api, forCtx);
1369
1382
  const items = createMemo(() => trackForCollection(evalRead(props.$for, evalCtx, ns, `${fullKey}:$for`)));
1370
1383
  const $keyProp = props.$key;
@@ -1377,8 +1390,10 @@
1377
1390
  disposedSlots.add(slot);
1378
1391
  leavingSlots.delete(slot);
1379
1392
  callHook(g, name, "onUnmount");
1380
- disposeComponent(slot.el);
1381
- slot.el.remove();
1393
+ if (slot.el) {
1394
+ disposeComponent(slot.el);
1395
+ slot.el.remove();
1396
+ }
1382
1397
  if (slot.dispose)
1383
1398
  slot.dispose();
1384
1399
  };
@@ -1403,12 +1418,16 @@
1403
1418
  }
1404
1419
  }
1405
1420
  for (const slot of deletedSlots) {
1406
- container.appendChild(slot.el);
1407
1421
  leavingSlots.add(slot);
1422
+ if (!slot.el) {
1423
+ disposeSlot(slot);
1424
+ continue;
1425
+ }
1408
1426
  applyLeaveAnimation(slot.el, slot.props, () => {
1409
1427
  disposeSlot(slot);
1410
1428
  });
1411
1429
  }
1430
+ let cursor = startAnchor;
1412
1431
  arr.forEach((item, index) => {
1413
1432
  item = asReactiveValue(item, g);
1414
1433
  const keyVal = newKeys[index];
@@ -1436,20 +1455,22 @@
1436
1455
  const indexSignal = createSignal(index);
1437
1456
  const revisionSignal = createSignal(0);
1438
1457
  slot = renderAndMountSlot(item, index, keyVal, indexSignal, revisionSignal, renderer, type, name, props, container, g, components, componentTypes, api, forCtx, ns, fullKey, options);
1439
- if (slot.el) {
1440
- applyEnterAnimation(slot.el, slot.props);
1441
- callHook(g, name, "onMount");
1458
+ if (!slot.el) {
1459
+ disposeSlot(slot);
1460
+ return;
1442
1461
  }
1462
+ applyEnterAnimation(slot.el, slot.props);
1463
+ callHook(g, name, "onMount");
1443
1464
  slotMap.set(keyVal, slot);
1444
1465
  }
1445
- const refChild = forWrapper.children[index];
1446
- if (slot.el && refChild !== slot.el) {
1447
- forWrapper.insertBefore(slot.el, refChild ?? null);
1466
+ const nextChild = cursor.nextSibling;
1467
+ if (slot.el && nextChild !== slot.el) {
1468
+ container.insertBefore(slot.el, nextChild ?? endAnchor);
1469
+ }
1470
+ if (slot.el) {
1471
+ cursor = slot.el;
1448
1472
  }
1449
1473
  });
1450
- while (forWrapper.children.length > arr.length) {
1451
- forWrapper.lastChild.remove();
1452
- }
1453
1474
  });
1454
1475
  onCleanup(() => {
1455
1476
  for (const slot of Array.from(slotMap.values()))
@@ -1457,7 +1478,8 @@
1457
1478
  slotMap.clear();
1458
1479
  for (const slot of Array.from(leavingSlots))
1459
1480
  disposeSlot(slot);
1460
- forWrapper.remove();
1481
+ startAnchor.remove();
1482
+ endAnchor.remove();
1461
1483
  });
1462
1484
  }
1463
1485
  function renderNormalNode(fullKey, props, container, g, components, componentTypes, api, forCtx, ns, options) {
@@ -1834,7 +1856,7 @@ ${parseSource}
1834
1856
  var parseSlexKitDsl = parseSlexSource;
1835
1857
 
1836
1858
  // src/version.ts
1837
- var SLEXKIT_VERSION = "0.3.1";
1859
+ var SLEXKIT_VERSION = "0.3.3";
1838
1860
  var SLEX_PROTOCOL_VERSION = "0.1";
1839
1861
  var SLEXKIT_COMPONENTS_VERSION = SLEXKIT_VERSION;
1840
1862
  function getSlexKitInfo() {
@@ -12241,7 +12263,7 @@ ${component_stack}
12241
12263
  }
12242
12264
 
12243
12265
  // src/components/svelte/input/Slider.svelte
12244
- var root5 = from_html(`<div class="slex-slider-field"><div class="slex-slider-label"><span class="slex-slider-label-text"><!> <span> </span></span> <span class="slex-slider-value"> <!></span></div> <input type="range" class="slex-slider"/></div>`);
12266
+ var root5 = from_html(`<div class="slex-slider-field"><div class="slex-slider-label"><span class="slex-slider-label-text"><!> <span> </span></span> <span class="slex-slider-value"> <!></span></div> <div class="slex-slider-control"><span class="slex-slider-track" aria-hidden="true"></span> <input type="range" class="slex-slider"/></div></div>`);
12245
12267
  function Slider($$anchor, $$props) {
12246
12268
  push($$props, true);
12247
12269
  let p = state(proxy({}));
@@ -12341,30 +12363,32 @@ ${component_stack}
12341
12363
  }
12342
12364
  reset(span_2);
12343
12365
  reset(div_1);
12344
- var input_1 = sibling(div_1, 2);
12366
+ var div_2 = sibling(div_1, 2);
12367
+ var input_1 = sibling(child(div_2), 2);
12345
12368
  remove_input_defaults(input_1);
12369
+ reset(div_2);
12346
12370
  reset(div);
12347
12371
  template_effect(($0, $1, $2, $3, $4, $5, $6, $7, $8) => {
12348
12372
  set_attribute2(div, "data-orientation", $0);
12349
12373
  set_text(text_1, $1);
12350
12374
  set_text(text_2, $2);
12351
- set_attribute2(input_1, "min", $3);
12352
- set_attribute2(input_1, "max", $4);
12353
- set_attribute2(input_1, "step", $5);
12354
- set_value(input_1, $6);
12375
+ set_style(div_2, $3);
12376
+ set_attribute2(input_1, "min", $4);
12377
+ set_attribute2(input_1, "max", $5);
12378
+ set_attribute2(input_1, "step", $6);
12379
+ set_value(input_1, $7);
12355
12380
  input_1.disabled = !!get2(p).disabled;
12356
- set_attribute2(input_1, "aria-label", $7);
12357
- set_style(input_1, $8);
12381
+ set_attribute2(input_1, "aria-label", $8);
12358
12382
  }, [
12359
12383
  () => text2(get2(p).orientation, "horizontal"),
12360
12384
  () => text2(get2(p).label ?? $$props.componentName),
12361
12385
  () => text2(get2(value) ?? 0),
12386
+ () => `--slex-slider-progress: ${sliderProgress(get2(value), get2(p).min, get2(p).max)}`,
12362
12387
  () => Number(get2(p).min ?? 0),
12363
12388
  () => Number(get2(p).max ?? 100),
12364
12389
  () => Number(get2(p).step ?? 1),
12365
12390
  () => Number(get2(value) ?? 0),
12366
- () => text2(get2(p)["aria-label"] ?? get2(p).ariaLabel ?? get2(p).label ?? $$props.componentName),
12367
- () => `--slex-slider-progress: ${sliderProgress(get2(value), get2(p).min, get2(p).max)}`
12391
+ () => text2(get2(p)["aria-label"] ?? get2(p).ariaLabel ?? get2(p).label ?? $$props.componentName)
12368
12392
  ]);
12369
12393
  delegated("pointerdown", input_1, grabSlider);
12370
12394
  delegated("input", input_1, (event2) => choose(Number(event2.target.value)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slexkit",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Zero-build, Markdown-friendly reactive UI runtime for AI output.",
5
5
  "author": "SlexKit contributors",
6
6
  "type": "module",
@@ -80,17 +80,19 @@
80
80
  </span>
81
81
  <span class="slex-slider-value">{text(value ?? 0)}{#if p.unit} {text(p.unit)}{/if}</span>
82
82
  </div>
83
- <input
84
- type="range"
85
- class="slex-slider"
86
- min={Number(p.min ?? 0)}
87
- max={Number(p.max ?? 100)}
88
- step={Number(p.step ?? 1)}
89
- value={Number(value ?? 0)}
90
- disabled={!!p.disabled}
91
- aria-label={text(p["aria-label"] ?? p.ariaLabel ?? p.label ?? componentName)}
92
- style={`--slex-slider-progress: ${sliderProgress(value, p.min, p.max)}`}
93
- onpointerdown={grabSlider}
94
- oninput={(event) => choose(Number((event.target as HTMLInputElement).value))}
95
- />
83
+ <div class="slex-slider-control" style={`--slex-slider-progress: ${sliderProgress(value, p.min, p.max)}`}>
84
+ <span class="slex-slider-track" aria-hidden="true"></span>
85
+ <input
86
+ type="range"
87
+ class="slex-slider"
88
+ min={Number(p.min ?? 0)}
89
+ max={Number(p.max ?? 100)}
90
+ step={Number(p.step ?? 1)}
91
+ value={Number(value ?? 0)}
92
+ disabled={!!p.disabled}
93
+ aria-label={text(p["aria-label"] ?? p.ariaLabel ?? p.label ?? componentName)}
94
+ onpointerdown={grabSlider}
95
+ oninput={(event) => choose(Number((event.target as HTMLInputElement).value))}
96
+ />
97
+ </div>
96
98
  </div>
@@ -30,22 +30,71 @@
30
30
  font-weight: 600;
31
31
  }
32
32
 
33
+ .slex-slider-control {
34
+ position: relative;
35
+ box-sizing: border-box;
36
+ width: 100%;
37
+ height: 1rem;
38
+ }
39
+
40
+ .slex-slider-track {
41
+ position: absolute;
42
+ inset-inline: 0;
43
+ top: 50%;
44
+ height: 0.5rem;
45
+ border-radius: 999px;
46
+ background: linear-gradient(
47
+ to right,
48
+ var(--primary) 0%,
49
+ var(--primary) var(--slex-slider-progress, 0%),
50
+ var(--secondary) var(--slex-slider-progress, 0%),
51
+ var(--secondary) 100%
52
+ );
53
+ pointer-events: none;
54
+ transform: translateY(-50%);
55
+ }
56
+
33
57
  .slex-slider {
58
+ position: relative;
59
+ z-index: 1;
34
60
  box-sizing: border-box;
61
+ display: block;
35
62
  width: 100%;
36
63
  height: 1rem;
64
+ margin: 0;
37
65
  padding: 0;
38
66
  border: 0;
39
67
  border-radius: 999px;
40
68
  -webkit-appearance: none;
41
69
  appearance: none;
42
70
  background: transparent;
71
+ color: transparent;
43
72
  accent-color: var(--primary);
44
73
  cursor: pointer;
45
74
  overflow: visible;
46
75
  transition: box-shadow 150ms ease, filter 150ms ease;
47
76
  }
48
77
 
78
+ .slexkit-root .slex-slider-control input.slex-slider {
79
+ position: relative;
80
+ z-index: 1;
81
+ box-sizing: border-box;
82
+ display: block;
83
+ width: 100%;
84
+ height: 1rem;
85
+ min-height: 0;
86
+ margin: 0;
87
+ padding: 0;
88
+ border: 0;
89
+ border-radius: 999px;
90
+ box-shadow: none;
91
+ background: transparent;
92
+ color: transparent;
93
+ -webkit-appearance: none;
94
+ appearance: none;
95
+ overflow: visible;
96
+ }
97
+
49
98
  .slex-slider:focus-visible {
50
99
  outline: 2px solid var(--ring);
51
100
  outline-offset: 4px;
@@ -55,7 +104,7 @@
55
104
  box-sizing: border-box;
56
105
  width: 1rem;
57
106
  height: 1rem;
58
- margin-top: -0.25rem;
107
+ margin-top: 0;
59
108
  border: 2px solid var(--primary);
60
109
  border-radius: 999px;
61
110
  background-color: var(--background);
@@ -69,16 +118,10 @@
69
118
  .slex-slider::-webkit-slider-runnable-track {
70
119
  box-sizing: border-box;
71
120
  width: 100%;
72
- height: 0.5rem;
121
+ height: 1rem;
73
122
  border: 0;
74
123
  border-radius: 999px;
75
- background: linear-gradient(
76
- to right,
77
- var(--primary) 0%,
78
- var(--primary) var(--slex-slider-progress, 0%),
79
- var(--secondary) var(--slex-slider-progress, 0%),
80
- var(--secondary) 100%
81
- );
124
+ background: transparent;
82
125
  }
83
126
 
84
127
  .slex-slider::-moz-range-thumb {
@@ -114,16 +157,16 @@
114
157
  }
115
158
 
116
159
  .slex-slider::-moz-range-track {
117
- height: 0.5rem;
160
+ height: 1rem;
118
161
  border: 0;
119
162
  border-radius: 999px;
120
- background: var(--secondary);
163
+ background: transparent;
121
164
  }
122
165
 
123
166
  .slex-slider::-moz-range-progress {
124
- height: 0.5rem;
167
+ height: 1rem;
125
168
  border-radius: 999px;
126
- background: var(--primary);
169
+ background: transparent;
127
170
  }
128
171
 
129
172
  .slex-slider-label-text {
@@ -56,11 +56,40 @@
56
56
  transition: border-color 150ms ease, box-shadow 150ms ease;
57
57
  }
58
58
 
59
+ .slexkit-root .slex-input-control input.slex-input {
60
+ box-sizing: border-box;
61
+ display: block;
62
+ flex: 1 1 auto;
63
+ width: 100%;
64
+ min-width: 0;
65
+ min-height: 2.5625rem;
66
+ height: auto;
67
+ margin: 0;
68
+ padding: 0.5rem 0.75rem;
69
+ border: 1px solid var(--input);
70
+ border-radius: var(--radius);
71
+ box-shadow: none;
72
+ background: var(--background);
73
+ background-clip: padding-box;
74
+ color: var(--foreground);
75
+ font-family: inherit;
76
+ font-size: 0.875rem;
77
+ line-height: 1.5;
78
+ outline: none;
79
+ -webkit-appearance: none;
80
+ appearance: none;
81
+ }
82
+
59
83
  .slex-input-control[data-has-unit="true"] .slex-input {
60
84
  border-top-right-radius: 0;
61
85
  border-bottom-right-radius: 0;
62
86
  }
63
87
 
88
+ .slexkit-root .slex-input-control[data-has-unit="true"] input.slex-input {
89
+ border-top-right-radius: 0;
90
+ border-bottom-right-radius: 0;
91
+ }
92
+
64
93
  .slex-input-unit {
65
94
  box-sizing: border-box;
66
95
  display: inline-flex;
@@ -32,52 +32,6 @@
32
32
  box-sizing: border-box;
33
33
  }
34
34
 
35
- body[data-mobile-nav-open] {
36
- overflow: hidden;
37
- overscroll-behavior: contain;
38
- }
39
-
40
- #mobileNav {
41
- --mobile-nav-backdrop-opacity: 0;
42
- --mobile-nav-panel-translate: -100%;
43
- pointer-events: none;
44
- }
45
-
46
- #mobileNav[data-open="true"] {
47
- --mobile-nav-backdrop-opacity: 1;
48
- --mobile-nav-panel-translate: 0px;
49
- pointer-events: auto;
50
- }
51
-
52
- #mobileNav [data-mobile-nav-backdrop] {
53
- opacity: var(--mobile-nav-backdrop-opacity);
54
- touch-action: pan-y;
55
- transition: opacity 180ms ease;
56
- }
57
-
58
- #mobileNav [data-mobile-nav-panel] {
59
- transform: translateX(var(--mobile-nav-panel-translate));
60
- touch-action: pan-y;
61
- transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
62
- will-change: transform;
63
- }
64
-
65
- #mobileNav[data-dragging="true"] [data-mobile-nav-backdrop],
66
- #mobileNav[data-dragging="true"] [data-mobile-nav-panel] {
67
- transition: none;
68
- }
69
-
70
- @media (prefers-reduced-motion: reduce) {
71
- #mobileNav [data-mobile-nav-backdrop],
72
- #mobileNav [data-mobile-nav-panel] {
73
- transition: none;
74
- }
75
- }
76
-
77
- .slexkit-for-wrapper {
78
- display: contents;
79
- }
80
-
81
35
  .slexkit-source-toolbar {
82
36
  display: flex;
83
37
  align-items: center;