@mulsense/xnew 0.6.1 → 0.6.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/xnew.d.ts CHANGED
@@ -175,7 +175,7 @@ interface CreateUnit {
175
175
  (target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
176
176
  }
177
177
 
178
- declare function OpenAndClose(unit: Unit, { open }?: {
178
+ declare function OpenAndClose(unit: Unit, { open }: {
179
179
  open?: boolean;
180
180
  }): {
181
181
  toggle(duration?: number, easing?: string): void;
@@ -183,9 +183,7 @@ declare function OpenAndClose(unit: Unit, { open }?: {
183
183
  close(duration?: number, easing?: string): void;
184
184
  };
185
185
  declare function Accordion(unit: Unit): void;
186
- declare function Modal(unit: Unit, { background }?: {
187
- background?: string;
188
- }): void;
186
+ declare function Modal(unit: Unit): void;
189
187
 
190
188
  type ScreenFit = 'contain' | 'cover';
191
189
  declare function Screen(unit: Unit, { aspect, fit }?: {
@@ -212,13 +210,13 @@ declare function DPad(unit: Unit, { diagonal, stroke, strokeOpacity, strokeWidth
212
210
  fillOpacity?: number;
213
211
  }): void;
214
212
 
215
- interface GUIPanelOptions {
213
+ interface PanelOptions {
216
214
  name?: string;
217
215
  open?: boolean;
218
216
  params?: Record<string, any>;
219
217
  }
220
- declare function GUIPanel(unit: Unit, { name, open, params }: GUIPanelOptions): {
221
- group({ name, open, params }: GUIPanelOptions, inner: Function): Unit;
218
+ declare function Panel(unit: Unit, { name, open, params }: PanelOptions): {
219
+ group({ name, open, params }: PanelOptions, inner: Function): Unit;
222
220
  button(key: string): Unit;
223
221
  select(key: string, { options }?: {
224
222
  options?: string[];
@@ -299,7 +297,7 @@ declare const xnew: CreateUnit & {
299
297
  OpenAndClose: typeof OpenAndClose;
300
298
  AnalogStick: typeof AnalogStick;
301
299
  DPad: typeof DPad;
302
- GUIPanel: typeof GUIPanel;
300
+ Panel: typeof Panel;
303
301
  Accordion: typeof Accordion;
304
302
  Modal: typeof Modal;
305
303
  };
package/dist/xnew.js CHANGED
@@ -1273,48 +1273,33 @@
1273
1273
  },
1274
1274
  });
1275
1275
 
1276
- function OpenAndClose(unit, { open = false } = {}) {
1276
+ function OpenAndClose(unit, { open = false }) {
1277
1277
  let state = open ? 1.0 : 0.0;
1278
- let direction = state === 1.0 ? +1 : (state === 0.0 ? -1 : null);
1278
+ let sign = open ? +1 : -1;
1279
1279
  let timer = xnew$1.timeout(() => xnew$1.emit('-transition', { state }));
1280
1280
  return {
1281
1281
  toggle(duration = 200, easing = 'ease') {
1282
- if (direction === null || direction < 0) {
1283
- unit.open(duration, easing);
1284
- }
1285
- else {
1286
- unit.close(duration, easing);
1287
- }
1282
+ sign < 0 ? unit.open(duration, easing) : unit.close(duration, easing);
1288
1283
  },
1289
1284
  open(duration = 200, easing = 'ease') {
1290
- if (direction === null || direction < 0) {
1291
- direction = +1;
1292
- const d = 1 - state;
1293
- timer === null || timer === void 0 ? void 0 : timer.clear();
1294
- timer = xnew$1.transition((x) => {
1295
- const y = x < 1.0 ? (1 - x) * d : 0.0;
1296
- state = 1.0 - y;
1297
- xnew$1.emit('-transition', { state });
1298
- }, duration * d, easing)
1299
- .timeout(() => {
1300
- xnew$1.emit('-opened', { state });
1301
- });
1302
- }
1285
+ sign = +1;
1286
+ const d = 1 - state;
1287
+ timer === null || timer === void 0 ? void 0 : timer.clear();
1288
+ timer = xnew$1.transition((x) => {
1289
+ state = 1.0 - (x < 1.0 ? (1 - x) * d : 0.0);
1290
+ xnew$1.emit('-transition', { state });
1291
+ }, duration * d, easing)
1292
+ .timeout(() => xnew$1.emit('-opened', { state }));
1303
1293
  },
1304
1294
  close(duration = 200, easing = 'ease') {
1305
- if (direction === null || direction > 0) {
1306
- direction = -1;
1307
- const d = state;
1308
- timer === null || timer === void 0 ? void 0 : timer.clear();
1309
- timer = xnew$1.transition((x) => {
1310
- const y = x < 1.0 ? (1 - x) * d : 0.0;
1311
- state = y;
1312
- xnew$1.emit('-transition', { state });
1313
- }, duration * d, easing)
1314
- .timeout(() => {
1315
- xnew$1.emit('-closed', { state });
1316
- });
1317
- }
1295
+ sign = -1;
1296
+ const d = state;
1297
+ timer === null || timer === void 0 ? void 0 : timer.clear();
1298
+ timer = xnew$1.transition((x) => {
1299
+ state = x < 1.0 ? (1 - x) * d : 0.0;
1300
+ xnew$1.emit('-transition', { state });
1301
+ }, duration * d, easing)
1302
+ .timeout(() => xnew$1.emit('-closed', { state }));
1318
1303
  },
1319
1304
  };
1320
1305
  }
@@ -1327,17 +1312,18 @@
1327
1312
  outer.style.opacity = state.toString();
1328
1313
  });
1329
1314
  }
1330
- function Modal(unit, { background = 'rgba(0, 0, 0, 0.1)' } = {}) {
1315
+ function Modal(unit) {
1331
1316
  const system = xnew$1.context(OpenAndClose);
1317
+ system.open();
1332
1318
  system.on('-closed', () => unit.finalize());
1333
- xnew$1.nest('<div style="position: fixed; inset: 0; z-index: 1000;">');
1334
- unit.on('click', ({ event }) => system.close());
1335
- const outer = xnew$1.nest(`<div style="width: 100%; height: 100%; opacity: 0;"">`);
1336
- xnew$1.nest('<div style="position: absolute; inset: 0; margin: auto; width: max-content; height: max-content;">');
1337
- unit.on('click', ({ event }) => event.stopPropagation());
1338
- outer.style.background = background;
1319
+ xnew$1.nest('<div style="position: absolute; inset: 0; z-index: 1000; opacity: 0;">');
1320
+ unit.on('click', ({ event }) => {
1321
+ if (event.target === unit.element) {
1322
+ system.close();
1323
+ }
1324
+ });
1339
1325
  system.on('-transition', ({ state }) => {
1340
- outer.style.opacity = state.toString();
1326
+ unit.element.style.opacity = state.toString();
1341
1327
  });
1342
1328
  }
1343
1329
 
@@ -1462,54 +1448,40 @@
1462
1448
  });
1463
1449
  }
1464
1450
 
1465
- function GUIPanel(unit, { name, open = false, params }) {
1451
+ function Panel(unit, { name, open = false, params }) {
1466
1452
  const object = params !== null && params !== void 0 ? params : {};
1467
1453
  xnew$1.extend(Group, { name, open });
1468
1454
  return {
1469
1455
  group({ name, open, params }, inner) {
1470
1456
  const group = xnew$1((unit) => {
1471
- xnew$1.extend(GUIPanel, { name, open, params: params !== null && params !== void 0 ? params : object });
1457
+ xnew$1.extend(Panel, { name, open, params: params !== null && params !== void 0 ? params : object });
1472
1458
  inner(unit);
1473
1459
  });
1474
- group.on('-eventcapture', ({ event, key, value }) => {
1475
- xnew$1.emit('-eventcapture', { event, key, value });
1476
- });
1477
1460
  return group;
1478
1461
  },
1479
1462
  button(key) {
1480
1463
  const button = xnew$1(Button, { key });
1481
- button.on('click', ({ event }) => {
1482
- xnew$1.emit('-eventcapture', { event, key });
1483
- });
1484
1464
  return button;
1485
1465
  },
1486
1466
  select(key, { options = [] } = {}) {
1487
1467
  var _a, _b;
1488
1468
  object[key] = (_b = (_a = object[key]) !== null && _a !== void 0 ? _a : options[0]) !== null && _b !== void 0 ? _b : '';
1489
1469
  const select = xnew$1(Select, { key, value: object[key], options });
1490
- select.on('input', ({ event, value }) => {
1491
- xnew$1.emit('-eventcapture', { event, key, value });
1492
- });
1470
+ select.on('input', ({ value }) => object[key] = value);
1493
1471
  return select;
1494
1472
  },
1495
1473
  range(key, options = {}) {
1496
- var _a;
1497
- object[key] = (_a = object[key]) !== null && _a !== void 0 ? _a : 0;
1474
+ var _a, _b;
1475
+ object[key] = (_b = (_a = object[key]) !== null && _a !== void 0 ? _a : options.min) !== null && _b !== void 0 ? _b : 0;
1498
1476
  const number = xnew$1(Range, Object.assign({ key, value: object[key] }, options));
1499
- number.on('input', ({ event, value }) => {
1500
- object[key] = value;
1501
- xnew$1.emit('-eventcapture', { event, key, value });
1502
- });
1477
+ number.on('input', ({ value }) => object[key] = value);
1503
1478
  return number;
1504
1479
  },
1505
1480
  checkbox(key) {
1506
1481
  var _a;
1507
1482
  object[key] = (_a = object[key]) !== null && _a !== void 0 ? _a : false;
1508
1483
  const checkbox = xnew$1(Checkbox, { key, value: object[key] });
1509
- checkbox.on('input', ({ event, value }) => {
1510
- object[key] = value;
1511
- xnew$1.emit('-eventcapture', { event, key, value });
1512
- });
1484
+ checkbox.on('input', ({ value }) => object[key] = value);
1513
1485
  return checkbox;
1514
1486
  },
1515
1487
  separator() {
@@ -1520,7 +1492,7 @@
1520
1492
  function Group(group, { name, open = false }) {
1521
1493
  xnew$1.extend(OpenAndClose, { open });
1522
1494
  if (name) {
1523
- xnew$1('<div style="display: flex; align-items: center; cursor: pointer;">', (unit) => {
1495
+ xnew$1('<div style="height: 2rem; margin: 0.125rem 0; display: flex; align-items: center; cursor: pointer; user-select: none;">', (unit) => {
1524
1496
  unit.on('click', () => group.toggle());
1525
1497
  xnew$1('<svg viewBox="0 0 12 12" style="width: 1rem; height: 1rem; margin-right: 0.25rem;" fill="none" stroke="currentColor">', (unit) => {
1526
1498
  xnew$1('<path d="M6 2 10 6 6 10" />');
@@ -1532,11 +1504,11 @@
1532
1504
  xnew$1.extend(Accordion);
1533
1505
  }
1534
1506
  function Button(unit, { key = '' }) {
1535
- xnew$1.nest('<button style="margin: 0.125rem; padding: 0.125rem; border: 1px solid; border-radius: 0.25rem; cursor: pointer;">');
1507
+ xnew$1.nest('<button style="margin: 0.125rem; height: 2rem; border: 1px solid; border-radius: 0.25rem; cursor: pointer;">');
1536
1508
  unit.element.textContent = key;
1537
1509
  unit.on('pointerover', () => {
1538
- unit.element.style.background = 'rgba(0, 0, 128, 0.1)';
1539
- unit.element.style.borderColor = 'blue';
1510
+ unit.element.style.background = 'color-mix(in srgb, currentColor 5%, transparent)';
1511
+ unit.element.style.borderColor = 'color-mix(in srgb, currentColor 40%, transparent)';
1540
1512
  });
1541
1513
  unit.on('pointerout', () => {
1542
1514
  unit.element.style.background = '';
@@ -1550,28 +1522,51 @@
1550
1522
  });
1551
1523
  }
1552
1524
  function Separator(unit) {
1553
- xnew$1.nest('<div style="margin: 0.5rem 0; border-top: 1px solid;">');
1525
+ xnew$1.nest('<div style="margin: 0.5rem 0; border-top: 1px solid color-mix(in srgb, currentColor 40%, transparent);">');
1554
1526
  }
1555
1527
  function Range(unit, { key = '', value, min = 0, max = 100, step = 1 }) {
1556
- xnew$1.nest(`<div style="margin: 0.125rem;">`);
1557
- const status = xnew$1('<div style="display: flex; justify-content: space-between;">', (unit) => {
1558
- xnew$1('<div style="flex: 1;">', key);
1559
- xnew$1('<div key="status" style="flex: none;">', value);
1528
+ value = value !== null && value !== void 0 ? value : min;
1529
+ xnew$1.nest(`<div style="position: relative; height: 2rem; margin: 0.125rem 0; cursor: pointer; user-select: none;">`);
1530
+ // fill bar
1531
+ const ratio = (value - min) / (max - min);
1532
+ const fill = xnew$1(`<div style="position: absolute; top: 0; left: 0; bottom: 0; width: ${ratio * 100}%; background: color-mix(in srgb, currentColor 5%, transparent); border: 1px solid color-mix(in srgb, currentColor 40%, transparent); border-radius: 0.25rem; transition: width 0.05s;">`);
1533
+ // overlay labels
1534
+ const status = xnew$1('<div style="position: absolute; inset: 0; padding: 0 0.25rem; display: flex; justify-content: space-between; align-items: center; pointer-events: none;">', (unit) => {
1535
+ xnew$1('<div>', key);
1536
+ xnew$1('<div key="status">', value);
1560
1537
  });
1561
- xnew$1.nest(`<input type="range" name="${key}" min="${min}" max="${max}" step="${step}" value="${value}" style="width: 100%; cursor: pointer;">`);
1538
+ // hidden native input for interaction
1539
+ xnew$1.nest(`<input type="range" name="${key}" min="${min}" max="${max}" step="${step}" value="${value}" style="position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0;">`);
1562
1540
  unit.on('input', ({ event }) => {
1563
- status.element.querySelector('[key="status"]').textContent = event.target.value;
1541
+ const v = Number(event.target.value);
1542
+ const r = (v - min) / (max - min);
1543
+ fill.element.style.width = `${r * 100}%`;
1544
+ status.element.querySelector('[key="status"]').textContent = String(v);
1564
1545
  });
1565
1546
  }
1566
1547
  function Checkbox(unit, { key = '', value } = {}) {
1567
- xnew$1.nest(`<label style="margin: 0.125rem; display: flex; align-items: center; cursor: pointer;">`);
1548
+ xnew$1.nest(`<div style="position: relative; height: 2rem; margin: 0.125rem 0; padding: 0 0.25rem; display: flex; align-items: center; cursor: pointer; user-select: none;">`);
1568
1549
  xnew$1('<div style="flex: 1;">', key);
1569
- xnew$1.nest(`<input type="checkbox" name="${key}" ${value ? 'checked' : ''} style="margin-right: 0.25rem;">`);
1550
+ const box = xnew$1('<div style="width: 1.25rem; height: 1.25rem; border: 1px solid color-mix(in srgb, currentColor 40%, transparent); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center; transition: background 0.1s;">', () => {
1551
+ xnew$1('<svg viewBox="0 0 12 12" style="width: 1.25rem; height: 1.25rem; opacity: 0; transition: opacity 0.1s;" fill="none" stroke="color-mix(in srgb, currentColor 80%, transparent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">', () => {
1552
+ xnew$1('<path d="M2 6 5 9 10 3" />');
1553
+ });
1554
+ });
1555
+ const check = box.element.querySelector('svg');
1556
+ const update = (checked) => {
1557
+ box.element.style.background = checked ? 'color-mix(in srgb, currentColor 5%, transparent)' : '';
1558
+ check.style.opacity = checked ? '1' : '0';
1559
+ };
1560
+ update(!!value);
1561
+ xnew$1.nest(`<input type="checkbox" name="${key}" ${value ? 'checked' : ''} style="position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0;">`);
1562
+ unit.on('input', ({ event, value }) => {
1563
+ update(value);
1564
+ });
1570
1565
  }
1571
1566
  function Select(unit, { key = '', value, options = [] } = {}) {
1572
- xnew$1.nest(`<div style="margin: 0.125rem; display: flex; align-items: center;">`);
1567
+ xnew$1.nest(`<div style="height: 2rem; margin: 0.125rem 0; padding: 0 0.25rem; display: flex; align-items: center;">`);
1573
1568
  xnew$1('<div style="flex: 1;">', key);
1574
- xnew$1.nest(`<select name="${key}" style="padding: 0.125rem; border: 1px solid; border-radius: 0.25rem; cursor: pointer;">`);
1569
+ xnew$1.nest(`<select name="${key}" style="height: 2rem; padding: 0.25rem; border: 1px solid color-mix(in srgb, currentColor 40%, transparent); border-radius: 0.25rem; cursor: pointer; user-select: none;">`);
1575
1570
  for (const option of options) {
1576
1571
  xnew$1(`<option value="${option}" ${option === value ? 'selected' : ''}>`, option);
1577
1572
  }
@@ -1806,7 +1801,7 @@
1806
1801
  OpenAndClose,
1807
1802
  AnalogStick,
1808
1803
  DPad,
1809
- GUIPanel,
1804
+ Panel,
1810
1805
  Accordion,
1811
1806
  Modal,
1812
1807
  };
package/dist/xnew.mjs CHANGED
@@ -1267,48 +1267,33 @@ const xnew$1 = Object.assign(function (...args) {
1267
1267
  },
1268
1268
  });
1269
1269
 
1270
- function OpenAndClose(unit, { open = false } = {}) {
1270
+ function OpenAndClose(unit, { open = false }) {
1271
1271
  let state = open ? 1.0 : 0.0;
1272
- let direction = state === 1.0 ? +1 : (state === 0.0 ? -1 : null);
1272
+ let sign = open ? +1 : -1;
1273
1273
  let timer = xnew$1.timeout(() => xnew$1.emit('-transition', { state }));
1274
1274
  return {
1275
1275
  toggle(duration = 200, easing = 'ease') {
1276
- if (direction === null || direction < 0) {
1277
- unit.open(duration, easing);
1278
- }
1279
- else {
1280
- unit.close(duration, easing);
1281
- }
1276
+ sign < 0 ? unit.open(duration, easing) : unit.close(duration, easing);
1282
1277
  },
1283
1278
  open(duration = 200, easing = 'ease') {
1284
- if (direction === null || direction < 0) {
1285
- direction = +1;
1286
- const d = 1 - state;
1287
- timer === null || timer === void 0 ? void 0 : timer.clear();
1288
- timer = xnew$1.transition((x) => {
1289
- const y = x < 1.0 ? (1 - x) * d : 0.0;
1290
- state = 1.0 - y;
1291
- xnew$1.emit('-transition', { state });
1292
- }, duration * d, easing)
1293
- .timeout(() => {
1294
- xnew$1.emit('-opened', { state });
1295
- });
1296
- }
1279
+ sign = +1;
1280
+ const d = 1 - state;
1281
+ timer === null || timer === void 0 ? void 0 : timer.clear();
1282
+ timer = xnew$1.transition((x) => {
1283
+ state = 1.0 - (x < 1.0 ? (1 - x) * d : 0.0);
1284
+ xnew$1.emit('-transition', { state });
1285
+ }, duration * d, easing)
1286
+ .timeout(() => xnew$1.emit('-opened', { state }));
1297
1287
  },
1298
1288
  close(duration = 200, easing = 'ease') {
1299
- if (direction === null || direction > 0) {
1300
- direction = -1;
1301
- const d = state;
1302
- timer === null || timer === void 0 ? void 0 : timer.clear();
1303
- timer = xnew$1.transition((x) => {
1304
- const y = x < 1.0 ? (1 - x) * d : 0.0;
1305
- state = y;
1306
- xnew$1.emit('-transition', { state });
1307
- }, duration * d, easing)
1308
- .timeout(() => {
1309
- xnew$1.emit('-closed', { state });
1310
- });
1311
- }
1289
+ sign = -1;
1290
+ const d = state;
1291
+ timer === null || timer === void 0 ? void 0 : timer.clear();
1292
+ timer = xnew$1.transition((x) => {
1293
+ state = x < 1.0 ? (1 - x) * d : 0.0;
1294
+ xnew$1.emit('-transition', { state });
1295
+ }, duration * d, easing)
1296
+ .timeout(() => xnew$1.emit('-closed', { state }));
1312
1297
  },
1313
1298
  };
1314
1299
  }
@@ -1321,17 +1306,18 @@ function Accordion(unit) {
1321
1306
  outer.style.opacity = state.toString();
1322
1307
  });
1323
1308
  }
1324
- function Modal(unit, { background = 'rgba(0, 0, 0, 0.1)' } = {}) {
1309
+ function Modal(unit) {
1325
1310
  const system = xnew$1.context(OpenAndClose);
1311
+ system.open();
1326
1312
  system.on('-closed', () => unit.finalize());
1327
- xnew$1.nest('<div style="position: fixed; inset: 0; z-index: 1000;">');
1328
- unit.on('click', ({ event }) => system.close());
1329
- const outer = xnew$1.nest(`<div style="width: 100%; height: 100%; opacity: 0;"">`);
1330
- xnew$1.nest('<div style="position: absolute; inset: 0; margin: auto; width: max-content; height: max-content;">');
1331
- unit.on('click', ({ event }) => event.stopPropagation());
1332
- outer.style.background = background;
1313
+ xnew$1.nest('<div style="position: absolute; inset: 0; z-index: 1000; opacity: 0;">');
1314
+ unit.on('click', ({ event }) => {
1315
+ if (event.target === unit.element) {
1316
+ system.close();
1317
+ }
1318
+ });
1333
1319
  system.on('-transition', ({ state }) => {
1334
- outer.style.opacity = state.toString();
1320
+ unit.element.style.opacity = state.toString();
1335
1321
  });
1336
1322
  }
1337
1323
 
@@ -1456,54 +1442,40 @@ function DPad(unit, { diagonal = true, stroke = 'currentColor', strokeOpacity =
1456
1442
  });
1457
1443
  }
1458
1444
 
1459
- function GUIPanel(unit, { name, open = false, params }) {
1445
+ function Panel(unit, { name, open = false, params }) {
1460
1446
  const object = params !== null && params !== void 0 ? params : {};
1461
1447
  xnew$1.extend(Group, { name, open });
1462
1448
  return {
1463
1449
  group({ name, open, params }, inner) {
1464
1450
  const group = xnew$1((unit) => {
1465
- xnew$1.extend(GUIPanel, { name, open, params: params !== null && params !== void 0 ? params : object });
1451
+ xnew$1.extend(Panel, { name, open, params: params !== null && params !== void 0 ? params : object });
1466
1452
  inner(unit);
1467
1453
  });
1468
- group.on('-eventcapture', ({ event, key, value }) => {
1469
- xnew$1.emit('-eventcapture', { event, key, value });
1470
- });
1471
1454
  return group;
1472
1455
  },
1473
1456
  button(key) {
1474
1457
  const button = xnew$1(Button, { key });
1475
- button.on('click', ({ event }) => {
1476
- xnew$1.emit('-eventcapture', { event, key });
1477
- });
1478
1458
  return button;
1479
1459
  },
1480
1460
  select(key, { options = [] } = {}) {
1481
1461
  var _a, _b;
1482
1462
  object[key] = (_b = (_a = object[key]) !== null && _a !== void 0 ? _a : options[0]) !== null && _b !== void 0 ? _b : '';
1483
1463
  const select = xnew$1(Select, { key, value: object[key], options });
1484
- select.on('input', ({ event, value }) => {
1485
- xnew$1.emit('-eventcapture', { event, key, value });
1486
- });
1464
+ select.on('input', ({ value }) => object[key] = value);
1487
1465
  return select;
1488
1466
  },
1489
1467
  range(key, options = {}) {
1490
- var _a;
1491
- object[key] = (_a = object[key]) !== null && _a !== void 0 ? _a : 0;
1468
+ var _a, _b;
1469
+ object[key] = (_b = (_a = object[key]) !== null && _a !== void 0 ? _a : options.min) !== null && _b !== void 0 ? _b : 0;
1492
1470
  const number = xnew$1(Range, Object.assign({ key, value: object[key] }, options));
1493
- number.on('input', ({ event, value }) => {
1494
- object[key] = value;
1495
- xnew$1.emit('-eventcapture', { event, key, value });
1496
- });
1471
+ number.on('input', ({ value }) => object[key] = value);
1497
1472
  return number;
1498
1473
  },
1499
1474
  checkbox(key) {
1500
1475
  var _a;
1501
1476
  object[key] = (_a = object[key]) !== null && _a !== void 0 ? _a : false;
1502
1477
  const checkbox = xnew$1(Checkbox, { key, value: object[key] });
1503
- checkbox.on('input', ({ event, value }) => {
1504
- object[key] = value;
1505
- xnew$1.emit('-eventcapture', { event, key, value });
1506
- });
1478
+ checkbox.on('input', ({ value }) => object[key] = value);
1507
1479
  return checkbox;
1508
1480
  },
1509
1481
  separator() {
@@ -1514,7 +1486,7 @@ function GUIPanel(unit, { name, open = false, params }) {
1514
1486
  function Group(group, { name, open = false }) {
1515
1487
  xnew$1.extend(OpenAndClose, { open });
1516
1488
  if (name) {
1517
- xnew$1('<div style="display: flex; align-items: center; cursor: pointer;">', (unit) => {
1489
+ xnew$1('<div style="height: 2rem; margin: 0.125rem 0; display: flex; align-items: center; cursor: pointer; user-select: none;">', (unit) => {
1518
1490
  unit.on('click', () => group.toggle());
1519
1491
  xnew$1('<svg viewBox="0 0 12 12" style="width: 1rem; height: 1rem; margin-right: 0.25rem;" fill="none" stroke="currentColor">', (unit) => {
1520
1492
  xnew$1('<path d="M6 2 10 6 6 10" />');
@@ -1526,11 +1498,11 @@ function Group(group, { name, open = false }) {
1526
1498
  xnew$1.extend(Accordion);
1527
1499
  }
1528
1500
  function Button(unit, { key = '' }) {
1529
- xnew$1.nest('<button style="margin: 0.125rem; padding: 0.125rem; border: 1px solid; border-radius: 0.25rem; cursor: pointer;">');
1501
+ xnew$1.nest('<button style="margin: 0.125rem; height: 2rem; border: 1px solid; border-radius: 0.25rem; cursor: pointer;">');
1530
1502
  unit.element.textContent = key;
1531
1503
  unit.on('pointerover', () => {
1532
- unit.element.style.background = 'rgba(0, 0, 128, 0.1)';
1533
- unit.element.style.borderColor = 'blue';
1504
+ unit.element.style.background = 'color-mix(in srgb, currentColor 5%, transparent)';
1505
+ unit.element.style.borderColor = 'color-mix(in srgb, currentColor 40%, transparent)';
1534
1506
  });
1535
1507
  unit.on('pointerout', () => {
1536
1508
  unit.element.style.background = '';
@@ -1544,28 +1516,51 @@ function Button(unit, { key = '' }) {
1544
1516
  });
1545
1517
  }
1546
1518
  function Separator(unit) {
1547
- xnew$1.nest('<div style="margin: 0.5rem 0; border-top: 1px solid;">');
1519
+ xnew$1.nest('<div style="margin: 0.5rem 0; border-top: 1px solid color-mix(in srgb, currentColor 40%, transparent);">');
1548
1520
  }
1549
1521
  function Range(unit, { key = '', value, min = 0, max = 100, step = 1 }) {
1550
- xnew$1.nest(`<div style="margin: 0.125rem;">`);
1551
- const status = xnew$1('<div style="display: flex; justify-content: space-between;">', (unit) => {
1552
- xnew$1('<div style="flex: 1;">', key);
1553
- xnew$1('<div key="status" style="flex: none;">', value);
1522
+ value = value !== null && value !== void 0 ? value : min;
1523
+ xnew$1.nest(`<div style="position: relative; height: 2rem; margin: 0.125rem 0; cursor: pointer; user-select: none;">`);
1524
+ // fill bar
1525
+ const ratio = (value - min) / (max - min);
1526
+ const fill = xnew$1(`<div style="position: absolute; top: 0; left: 0; bottom: 0; width: ${ratio * 100}%; background: color-mix(in srgb, currentColor 5%, transparent); border: 1px solid color-mix(in srgb, currentColor 40%, transparent); border-radius: 0.25rem; transition: width 0.05s;">`);
1527
+ // overlay labels
1528
+ const status = xnew$1('<div style="position: absolute; inset: 0; padding: 0 0.25rem; display: flex; justify-content: space-between; align-items: center; pointer-events: none;">', (unit) => {
1529
+ xnew$1('<div>', key);
1530
+ xnew$1('<div key="status">', value);
1554
1531
  });
1555
- xnew$1.nest(`<input type="range" name="${key}" min="${min}" max="${max}" step="${step}" value="${value}" style="width: 100%; cursor: pointer;">`);
1532
+ // hidden native input for interaction
1533
+ xnew$1.nest(`<input type="range" name="${key}" min="${min}" max="${max}" step="${step}" value="${value}" style="position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0;">`);
1556
1534
  unit.on('input', ({ event }) => {
1557
- status.element.querySelector('[key="status"]').textContent = event.target.value;
1535
+ const v = Number(event.target.value);
1536
+ const r = (v - min) / (max - min);
1537
+ fill.element.style.width = `${r * 100}%`;
1538
+ status.element.querySelector('[key="status"]').textContent = String(v);
1558
1539
  });
1559
1540
  }
1560
1541
  function Checkbox(unit, { key = '', value } = {}) {
1561
- xnew$1.nest(`<label style="margin: 0.125rem; display: flex; align-items: center; cursor: pointer;">`);
1542
+ xnew$1.nest(`<div style="position: relative; height: 2rem; margin: 0.125rem 0; padding: 0 0.25rem; display: flex; align-items: center; cursor: pointer; user-select: none;">`);
1562
1543
  xnew$1('<div style="flex: 1;">', key);
1563
- xnew$1.nest(`<input type="checkbox" name="${key}" ${value ? 'checked' : ''} style="margin-right: 0.25rem;">`);
1544
+ const box = xnew$1('<div style="width: 1.25rem; height: 1.25rem; border: 1px solid color-mix(in srgb, currentColor 40%, transparent); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center; transition: background 0.1s;">', () => {
1545
+ xnew$1('<svg viewBox="0 0 12 12" style="width: 1.25rem; height: 1.25rem; opacity: 0; transition: opacity 0.1s;" fill="none" stroke="color-mix(in srgb, currentColor 80%, transparent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">', () => {
1546
+ xnew$1('<path d="M2 6 5 9 10 3" />');
1547
+ });
1548
+ });
1549
+ const check = box.element.querySelector('svg');
1550
+ const update = (checked) => {
1551
+ box.element.style.background = checked ? 'color-mix(in srgb, currentColor 5%, transparent)' : '';
1552
+ check.style.opacity = checked ? '1' : '0';
1553
+ };
1554
+ update(!!value);
1555
+ xnew$1.nest(`<input type="checkbox" name="${key}" ${value ? 'checked' : ''} style="position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0;">`);
1556
+ unit.on('input', ({ event, value }) => {
1557
+ update(value);
1558
+ });
1564
1559
  }
1565
1560
  function Select(unit, { key = '', value, options = [] } = {}) {
1566
- xnew$1.nest(`<div style="margin: 0.125rem; display: flex; align-items: center;">`);
1561
+ xnew$1.nest(`<div style="height: 2rem; margin: 0.125rem 0; padding: 0 0.25rem; display: flex; align-items: center;">`);
1567
1562
  xnew$1('<div style="flex: 1;">', key);
1568
- xnew$1.nest(`<select name="${key}" style="padding: 0.125rem; border: 1px solid; border-radius: 0.25rem; cursor: pointer;">`);
1563
+ xnew$1.nest(`<select name="${key}" style="height: 2rem; padding: 0.25rem; border: 1px solid color-mix(in srgb, currentColor 40%, transparent); border-radius: 0.25rem; cursor: pointer; user-select: none;">`);
1569
1564
  for (const option of options) {
1570
1565
  xnew$1(`<option value="${option}" ${option === value ? 'selected' : ''}>`, option);
1571
1566
  }
@@ -1800,7 +1795,7 @@ const basics = {
1800
1795
  OpenAndClose,
1801
1796
  AnalogStick,
1802
1797
  DPad,
1803
- GUIPanel,
1798
+ Panel,
1804
1799
  Accordion,
1805
1800
  Modal,
1806
1801
  };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "keywords": [
5
5
  "Component-Oriented Programming"
6
6
  ],
7
- "version": "0.6.1",
7
+ "version": "0.6.2",
8
8
  "main": "dist/xnew.js",
9
9
  "module": "dist/xnew.mjs",
10
10
  "types": "dist/xnew.d.ts",