@muten/shadcn 0.1.5 → 0.1.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muten/shadcn",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "shadcn-style component registry for muten - own-the-source parts you add with `muten add`.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -57,6 +57,7 @@ export function mount(el, inputs, on) {
57
57
  blocks: list(i.blocks).map((b) => ({ ...b, day: plain(b.day) })),
58
58
  queue: list(i.queue).map((q) => ({ ...q, day: plain(q.day) })), closed: list(i.closed).map(plain), loading: yes(i.loading),
59
59
  placing: (() => { const g = list(i.placing)[0]; return g && g.start ? { ...g, day: dayOf(g.resource, g.day) } : null; })(),
60
+ from: Number(i.from) || 9, to: Number(i.to) || 19,
60
61
  lang: i.lang === 'en' ? 'en' : 'es', overlap: ['never', 'allow'].includes(i.overlap) ? i.overlap : 'auto', currency: i.currency || '', locale: i.locale || '', cents: yes(i.cents),
61
62
  };
62
63
  };
@@ -540,7 +540,9 @@ let wheelsNow = [];
540
540
  const sheetOf = (name) => { agOwner = me; openModal(K(name), 'auto'); };
541
541
  let { resources, events, blocks = [], availability = () => [[9 * 60, 19 * 60]], free: freeList = null, queue = [], closed = [], loading = false,
542
542
  lang = 'es', words = {}, currency = '', locale = '', cents = false, overlap = 'auto', placing = null } = opts; // all of these can change later through update()
543
- const { from = 9, to = 19, slot = 30, hourPx = 56, onCreate = () => {}, onChange = () => {}, onAction = () => {}, onOpen = null, onBlock = null, onMove = null, onRange = () => {},
543
+ // the first and last hour can change with the data (a shop's hours arrive after the first paint): update() takes them
544
+ let { from = 9, to = 19 } = opts;
545
+ const { slot = 30, hourPx = 56, onCreate = () => {}, onChange = () => {}, onAction = () => {}, onOpen = null, onBlock = null, onMove = null, onRange = () => {},
544
546
  actions = null, createSheet = false, services = [], view: startView = 'day', sheet: sheetMode = 'built-in', drag: dragOn = true,
545
547
  resize: resizeMode = 'on', moveAcross = 'on',
546
548
  start: startDay = null, phone: phoneMode = '', hour12 = false, timeZone = '', phoneView = '', blockScope = 'each', phoneStrip = '' } = opts;
@@ -961,19 +963,27 @@ let wheelsNow = [];
961
963
  body.innerHTML = '<div class="cx-ag-datesheet"></div>';
962
964
  dateUI($('.cx-ag-datesheet', body), (r) => { closeModal(); applyDate(r); });
963
965
  };
966
+ let blockDay = null; // the one open day of the week, when the form had nothing to choose from
964
967
  const openBlock = () => { blockOpen = true; sheetOf('agBlock'); };
965
968
  CONTENT[K('agBlock')] = () => {
966
969
  $('#mdl-title').textContent = w.blockTitle; $('#mdl-desc').textContent = w.blockDesc;
967
970
  const sel = (id, label, v) => ui.field({ id, label, control: kit.timeButton(v, `id="${id}" data-blt="${label}" style="width:100%;justify-content:flex-start"`) });
968
- body.innerHTML = `${resources.length > 1 && blockScope !== 'all' ? ui.field({ id: 'bl-r', label: w.for, control: `<button type="button" class="cn-button cn-button-variant-outline cn-button-size-default cx-sel-btn cx-fill" id="bl-r" data-v="${who === 'all' ? 'all' : who}"></button>` }) : ''}<div class="cx-frange">${sel('bl-f', w.from, '13:00')}${sel('bl-t', w.to, '14:00')}</div>${ui.field({ id: 'bl-why', label: w.reasonLabel, control: ui.input({ id: 'bl-why', value: w.reasonDefault }), description: w.onlyYou })}`;
971
+ // the week shows seven days, so the form says which one it blocks: only days that open, from today on, the shown day first
972
+ const open = eff() === 'week' ? weekDays().filter((d) => !isClosed(d)) : [];
973
+ const ahead = open.filter((d) => +d >= +today), days = ahead.length ? ahead : open;
974
+ const pickDay = days.find((d) => sameDay(d, day)) || days[0];
975
+ const dayField = days.length > 1 ? ui.field({ id: 'bl-d', label: w.day, control: `<button type="button" class="cn-button cn-button-variant-outline cn-button-size-default cx-sel-btn cx-fill" id="bl-d" data-v="${+pickDay}"></button>` }) : '';
976
+ body.innerHTML = `${dayField}${resources.length > 1 && blockScope !== 'all' ? ui.field({ id: 'bl-r', label: w.for, control: `<button type="button" class="cn-button cn-button-variant-outline cn-button-size-default cx-sel-btn cx-fill" id="bl-r" data-v="${who === 'all' ? 'all' : who}"></button>` }) : ''}<div class="cx-frange">${sel('bl-f', w.from, '13:00')}${sel('bl-t', w.to, '14:00')}</div>${ui.field({ id: 'bl-why', label: w.reasonLabel, control: ui.input({ id: 'bl-why', value: w.reasonDefault }), description: w.onlyYou })}`;
969
977
  foot.innerHTML = ui.button({ label: w.cancel, size: 'default', attrs: 'data-dismiss', cls: 'cx-exit' }) + ui.button({ label: `${ui.icon('i-lock')}${w.block}`, variant: 'default', size: 'default', attrs: 'data-bl-go', cls: 'cx-go' });
978
+ const bd = $('#bl-d', body); if (bd) kit.selectMenu(bd, { label: w.day, value: bd.dataset.v, options: days.map((d) => ({ value: String(+d), label: `${w.dayL[d.getDay()]} ${d.getDate()}` })), onChange: (v) => { bd.dataset.v = v; } });
979
+ blockDay = days.length === 1 ? days[0] : null;
970
980
  const br = $('#bl-r', body); if (br) kit.selectMenu(br, { label: w.for, value: br.dataset.v, options: [{ value: 'all', label: w.wholeShop }, ...resources.map((r) => ({ value: r.id, label: r.name }))], onChange: (v) => { br.dataset.v = v; } });
971
981
  };
972
982
  body.addEventListener('click', async (e) => { const b = e.target.closest('[data-blt]'); if (agOwner !== me || !b || !blockOpen) return; const v = await kit.pickTime({ value: b.querySelector('span').textContent, label: b.dataset.blt, from, to, step: 15 }); if (!v) return; b.querySelector('span').textContent = v; b.removeAttribute('aria-invalid'); const fb = $('#bl-f span', body), tb = $('#bl-t span', body); if (toMin(tb.textContent) <= toMin(fb.textContent)) tb.textContent = toHM(Math.min(toMin(fb.textContent) + 60, to * 60)); });
973
983
  document.addEventListener('click', (e) => {
974
984
  if (agOwner !== me || !e.target.closest('[data-bl-go]') || !blockOpen) return;
975
985
  const f = toMin($('#bl-f span', body).textContent), t2 = toMin($('#bl-t span', body).textContent); if (t2 <= f) { $('#bl-t', body).setAttribute('aria-invalid', 'true'); return; }
976
- const b = { id: 'b' + Date.now(), resource: $('#bl-r', body)?.dataset.v || resources[0].id, day: new Date(day), start: toHM(f), dur: t2 - f, reason: $('#bl-why', body).value.trim() || w.blocked };
986
+ const b = { id: 'b' + Date.now(), resource: $('#bl-r', body)?.dataset.v || resources[0].id, day: $('#bl-d', body) ? new Date(+$('#bl-d', body).dataset.v) : new Date(blockDay || day), start: toHM(f), dur: t2 - f, reason: $('#bl-why', body).value.trim() || w.blocked };
977
987
  blockOpen = false; closeModal();
978
988
  if (onBlock) { onBlock(b); return; }
979
989
  blocks.push(b); paint(); onChange(events); island('done', w.blockedOk, 1800);
@@ -985,6 +995,7 @@ let wheelsNow = [];
985
995
  if ('resources' in next) resources = next.resources; if ('events' in next) events = next.events; if ('blocks' in next) blocks = next.blocks;
986
996
  if ('availability' in next) availability = next.availability; if ('free' in next) freeList = next.free; if ('queue' in next) queue = next.queue;
987
997
  if ('closed' in next) closed = next.closed; if ('loading' in next) loading = next.loading;
998
+ if (Number(next.from) >= 0 && Number(next.to) > Number(next.from)) { from = Number(next.from); to = Number(next.to); }
988
999
  if ('overlap' in next) overlap = next.overlap; if ('placing' in next) placing = next.placing; if ('currency' in next) currency = next.currency; if ('locale' in next) locale = next.locale; if ('cents' in next) cents = next.cents;
989
1000
  if ('lang' in next || 'words' in next) { lang = next.lang ?? lang; words = next.words ?? words; w = { ...(AG_WORDS[lang] || AG_WORDS.es), ...words }; }
990
1001
  if (who !== 'all' && !(who.startsWith('kind:') ? resources.some((r) => kindOf(r) === who.slice(5)) : resources.some((r) => r.id === who))) who = 'all';