{"_id":"@broberg/ui-controls-core","_rev":"4-caa5803e3c9af466ebdd89c4616a1310","name":"@broberg/ui-controls-core","dist-tags":{"latest":"0.2.3"},"versions":{"0.1.0":{"name":"@broberg/ui-controls-core","version":"0.1.0","keywords":["ui-controls","custom-select","datepicker","calendar","toast","modal","keyboard-navigation","headless","broberg"],"license":"MIT","_id":"@broberg/ui-controls-core@0.1.0","maintainers":[{"name":"cbroberg","email":"cb@webhouse.dk"}],"homepage":"https://github.com/broberg-ai/components#readme","bugs":{"url":"https://github.com/broberg-ai/components/issues"},"dist":{"shasum":"b11bc01d59f71e180ad9bc9d5b07c1118883e4a1","tarball":"https://registry.npmjs.org/@broberg/ui-controls-core/-/ui-controls-core-0.1.0.tgz","fileCount":8,"integrity":"sha512-HClDD17lYA9fIaCa6VPFM2nC0hw5rvfS+Q5t253XdUAGj8/bUZ5OHRzZCzAz8q5KXtTUbiBelAKk4YgSzHeSNQ==","signatures":[{"sig":"MEUCIQDUUBkDLv11ecC15Ctv6E8mWfognEWT51fzoZJgwxIaQgIgeSco8wQn5dRytgBaC0JRZIzWt9d2JR02ZUP52Zgt3sk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64635},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"2ba6981e1363d0df7df847c51e78cb27eda32de8","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"cbroberg","email":"cb@webhouse.dk"},"repository":{"url":"git+https://github.com/broberg-ai/components.git","type":"git","directory":"packages/ui-controls-core"},"_npmVersion":"11.10.1","description":"Headless logic for the estate's native-control replacements (Christian's no-native-dialogs/controls rule): Monday-first calendar math + DD-MM-YYYY/YYYY-MM-DD normalisation, a select keyboard-navigation reducer, an outside-click/scroll/resize handler, and ","directories":{},"sideEffects":false,"_nodeVersion":"25.7.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.0","happy-dom":"^15.0.0","typescript":"^5.6.0"},"_npmOperationalInternal":{"tmp":"tmp/ui-controls-core_0.1.0_1783789345146_0.328908611801513","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@broberg/ui-controls-core","version":"0.1.1","keywords":["ui-controls","custom-select","datepicker","calendar","toast","modal","keyboard-navigation","headless","broberg"],"license":"MIT","_id":"@broberg/ui-controls-core@0.1.1","maintainers":[{"name":"cbroberg","email":"cb@webhouse.dk"}],"homepage":"https://github.com/broberg-ai/components#readme","bugs":{"url":"https://github.com/broberg-ai/components/issues"},"dist":{"shasum":"e425be666afc644174a4e346ff5b67fab51939fa","tarball":"https://registry.npmjs.org/@broberg/ui-controls-core/-/ui-controls-core-0.1.1.tgz","fileCount":8,"integrity":"sha512-Uy/P5X4bJfEnIhxEY+KRsBdRux4Wjbinv392196Mihu52esqpkmpISJBtFU7u1MS31Bq1yxNG2ILWwhlaYYCRg==","signatures":[{"sig":"MEUCIQCwYe1Ujtd/Qcv93JQ72isY1vOUJLbY0oYTlg94HN5g8gIgRjQHKuFEMlcQnQ10/4WqOiVP9VXZlP+AgQ8LvMazAiY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@broberg%2fui-controls-core@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":67127},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"0d3728e7ed93613def52fe9f9cf8cb7ed20f0dfc","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d9a085b3-2da0-41fa-b81c-c58e70858dd0"}},"repository":{"url":"git+https://github.com/broberg-ai/components.git","type":"git","directory":"packages/ui-controls-core"},"_npmVersion":"11.5.1","description":"Headless logic for the estate's native-control replacements (Christian's no-native-dialogs/controls rule): Monday-first calendar math + DD-MM-YYYY/YYYY-MM-DD normalisation, a select keyboard-navigation reducer, an outside-click/scroll/resize handler, and ","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.0","happy-dom":"^15.0.0","typescript":"^5.6.0"},"_npmOperationalInternal":{"tmp":"tmp/ui-controls-core_0.1.1_1787988593604_0.9058261747003997","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@broberg/ui-controls-core","version":"0.2.2","keywords":["ui-controls","custom-select","datepicker","calendar","toast","modal","keyboard-navigation","headless","broberg"],"license":"MIT","_id":"@broberg/ui-controls-core@0.2.2","maintainers":[{"name":"cbroberg","email":"cb@webhouse.dk"}],"homepage":"https://github.com/broberg-ai/components#readme","bugs":{"url":"https://github.com/broberg-ai/components/issues"},"dist":{"shasum":"aa0010e7fc6e9caa4ea7ac4148849bb10e42db60","tarball":"https://registry.npmjs.org/@broberg/ui-controls-core/-/ui-controls-core-0.2.2.tgz","fileCount":8,"integrity":"sha512-zyi1I4fukYgN8LlwFFYIfKUNJNoAl8H+W3xePg32SqW4nbmEHpeAfBoIxjeput76S37nnMWFau4rWi0CSnFYRw==","signatures":[{"sig":"MEQCIChP4Cvkqb2fjc/wd1hA64LsvFkyKvvOwyJWiBlo01I/AiBrr21UAF5g6FmWBTKxz3SabdQvrQBvHkgdmIdtyjivHw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@broberg%2fui-controls-core@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":77351},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"71a7f1941211a3d8116f90041e77cace2a75e234","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d9a085b3-2da0-41fa-b81c-c58e70858dd0"}},"repository":{"url":"git+https://github.com/broberg-ai/components.git","type":"git","directory":"packages/ui-controls-core"},"_npmVersion":"11.5.1","description":"Headless logic for the estate's native-control replacements (Christian's no-native-dialogs/controls rule): Monday-first calendar math + DD-MM-YYYY/YYYY-MM-DD normalisation, a select keyboard-navigation reducer, an outside-click/scroll/resize handler, and ","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.0","happy-dom":"^15.0.0","typescript":"^5.6.0"},"_npmOperationalInternal":{"tmp":"tmp/ui-controls-core_0.2.2_1789045249458_0.6525454804598176","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@broberg/ui-controls-core","version":"0.2.3","description":"Headless logic for the estate's native-control replacements (Christian's no-native-dialogs/controls rule): Monday-first calendar math + DD-MM-YYYY/YYYY-MM-DD normalisation, a select keyboard-navigation reducer, an outside-click/scroll/resize handler, and ","type":"module","license":"MIT","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"scripts":{"build":"tsup","test":"vitest run","typecheck":"tsc --noEmit"},"devDependencies":{"happy-dom":"^15.0.0","tsup":"^8.3.0","typescript":"^5.6.0","vitest":"^2.1.0"},"keywords":["ui-controls","custom-select","datepicker","calendar","toast","modal","keyboard-navigation","headless","broberg"],"repository":{"type":"git","url":"git+https://github.com/broberg-ai/components.git","directory":"packages/ui-controls-core"},"publishConfig":{"access":"public"},"_id":"@broberg/ui-controls-core@0.2.3","gitHead":"ef9f6cca7969203a69faab4ec989d35447ef61f3","bugs":{"url":"https://github.com/broberg-ai/components/issues"},"homepage":"https://github.com/broberg-ai/components#readme","_nodeVersion":"22.23.2","_npmVersion":"11.5.1","dist":{"integrity":"sha512-EBPFtl3/pGqzpSOa/kopW9exJIcmPpFUqPXNDzco6MK5bxTqK1nJF6kAd3mDmiSEegqxDRD2F9PNy+cLS1il1w==","shasum":"c48ce5779dfec4aaf64fc8c4270c8bc5eb87bd30","tarball":"https://registry.npmjs.org/@broberg/ui-controls-core/-/ui-controls-core-0.2.3.tgz","fileCount":8,"unpackedSize":81053,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@broberg%2fui-controls-core@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDapRXBtxnvGPgmknKrYOFacMi7Y0eeAMziptqBkcl3ZAIhAOy5R2BHUs0qwrCxgoaqyoP+ykwF1mprKgiu6SbgCiuM"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d9a085b3-2da0-41fa-b81c-c58e70858dd0"}},"directories":{},"maintainers":[{"name":"cbroberg","email":"cb@webhouse.dk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ui-controls-core_0.2.3_1789046729722_0.8525078652672036"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-11T17:02:25.022Z","modified":"2026-09-10T13:25:30.334Z","0.1.0":"2026-07-11T17:02:25.263Z","0.1.1":"2026-08-29T07:29:53.734Z","0.2.2":"2026-09-10T13:00:49.633Z","0.2.3":"2026-09-10T13:25:29.859Z"},"bugs":{"url":"https://github.com/broberg-ai/components/issues"},"license":"MIT","homepage":"https://github.com/broberg-ai/components#readme","keywords":["ui-controls","custom-select","datepicker","calendar","toast","modal","keyboard-navigation","headless","broberg"],"repository":{"type":"git","url":"git+https://github.com/broberg-ai/components.git","directory":"packages/ui-controls-core"},"description":"Headless logic for the estate's native-control replacements (Christian's no-native-dialogs/controls rule): Monday-first calendar math + DD-MM-YYYY/YYYY-MM-DD normalisation, a select keyboard-navigation reducer, an outside-click/scroll/resize handler, and ","maintainers":[{"name":"cbroberg","email":"cb@webhouse.dk"}],"readme":"# @broberg/ui-controls-core\n\nThe **headless logic** behind the estate's native-control replacements — the\ncustom `<select>`, the date picker, the modal, the toast — that Christian's\n\"never native dialogs or form controls\" rule mandates. Pure TypeScript, zero\nJSX, zero deps. The React (`@broberg/ui-controls-react`) and Preact\n(`@broberg/ui-controls-preact`) adapters render on top; this owns the parts that\nmust behave identically across both.\n\n```bash\nnpm i @broberg/ui-controls-core\n```\n\n## Calendar\n\n```ts\nimport { buildMonthGrid, ymd, parseYmd, isInRange, monthLabel, normalizeYmd } from \"@broberg/ui-controls-core\";\n\nbuildMonthGrid(2026, 7);          // 42 Monday-first cells, padded → [{date,day,inMonth}, …]\nmonthLabel(2026, 7, \"da-DK\");     // \"juli 2026\"  (locale-delegated, no baked-in names)\nisInRange(\"2026-07-04\", \"2026-07-01\", \"2026-07-31\");   // true\n\n// Typed-input normalisation — disambiguates strictly by the 4-digit year:\nnormalizeYmd(\"03-04-2025\");       // \"2025-04-03\"  (3 April, never April-03)\nnormalizeYmd(\"2025-04-03\");       // \"2025-04-03\"\nnormalizeYmd(\"3.4.2025\");         // \"2025-04-03\"\n```\n\n## Select keyboard reducer\n\n```ts\nimport { selectKeyReducer } from \"@broberg/ui-controls-core\";\n\nlet state = { open: false, highlighted: -1 };\nconst { state: next, intent } = selectKeyReducer(state, event.key, options.length);\n// intent: \"open\" | \"close\" | { type: \"select\", index } | \"none\"\n// ArrowDown/Up wrap; Enter/Space select the highlight (or open); Escape closes.\n```\n\n## Outside-click / scroll / resize\n\n```ts\nimport { makeOutsideClickHandler } from \"@broberg/ui-controls-core\";\n\nconst handle = makeOutsideClickHandler(() => [triggerEl, menuEl], () => setOpen(false));\nhandle.attach();   // closes on a pointerdown outside all els, or on ancestor scroll / resize\nhandle.detach();   // (a fixed-position portal would otherwise drift from its trigger)\n```\n\n## Toast queue\n\n```ts\nimport { ToastQueue } from \"@broberg/ui-controls-core\";\n\nconst toasts = new ToastQueue({ maxVisible: 4, defaultDuration: 4000 });\nconst id = toasts.push({ message: \"Saved\", kind: \"success\" });   // auto-dismisses; 0 = sticky\ntoasts.dismiss(id);\ntoasts.subscribe((items) => render(items));   // items: { id, message, kind, duration }[]\n```\n\nDeterministic (monotonic ids, no `Math.random`/`Date.now`) so it's trivially\ntestable and SSR-safe. Caps at `maxVisible`, dropping the oldest.\n\n## License\n\nMIT · part of the [`@broberg/*`](https://discovery.broberg.ai) shared inventory.\n","readmeFilename":"README.md"}