@c2n/core 0.0.17 → 0.0.19

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/.tsbuildinfo CHANGED
@@ -1 +1 @@
1
- {"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/lit-html/development/directive.d.ts","../../../node_modules/@types/trusted-types/lib/index.d.ts","../../../node_modules/lit-html/development/lit-html.d.ts","../../../node_modules/lit-html/development/directives/class-map.d.ts","../src/css-helper.ts","../src/data-helper.ts","../../../node_modules/lit-html/development/is-server.d.ts","../../../node_modules/@lit/reactive-element/development/css-tag.d.ts","../../../node_modules/@lit/reactive-element/development/reactive-controller.d.ts","../../../node_modules/@lit/reactive-element/development/reactive-element.d.ts","../../../node_modules/lit-element/development/lit-element.d.ts","../../../node_modules/lit/development/index.d.ts","../src/dom-helper.ts","../../../node_modules/@lit/reactive-element/development/decorators/base.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/custom-element.d.ts","../src/element-helper.ts","../src/event-helper.ts","../../../node_modules/@lit/reactive-element/development/decorators/property.d.ts","../src/lit-helper.ts","../../../node_modules/@lit/context/development/lib/create-context.d.ts","../../../node_modules/@lit/context/development/lib/context-request-event.d.ts","../../../node_modules/@lit/context/development/lib/controllers/context-consumer.d.ts","../../../node_modules/@lit/context/development/lib/value-notifier.d.ts","../../../node_modules/@lit/context/development/lib/controllers/context-provider.d.ts","../../../node_modules/@lit/context/development/lib/context-root.d.ts","../../../node_modules/@lit/context/development/lib/decorators/provide.d.ts","../../../node_modules/@lit/context/development/lib/decorators/consume.d.ts","../../../node_modules/@lit/context/development/index.d.ts","../src/contexts/pager.ts","../src/controllers/breakpoints-observer.ts","../src/controllers/context-consumer.ts","../src/controllers/virtual-scroll.ts"],"fileIdsList":[[67,68,69,71,72,73,74],[67],[57,67],[57,67,68,70],[68],[61],[57,61],[55,56],[50,57],[50],[48,50],[48,49],[50,54,57,58],[75],[57],[57,75],[59],[51],[54,59],[62],[57,59,65]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"00cb63103f9670f8094c238a4a7e252c8b4c06ba371fea5c44add7e41b7247e4","impliedFormat":99},{"version":"15fe687c59d62741b4494d5e623d497d55eb38966ecf5bea7f36e48fc3fbe15e","impliedFormat":1},{"version":"e09db3291e6b440f7debed2227d8357e80c95987a0d0d67ac17521d8f7b11bdb","impliedFormat":99},{"version":"9e77270468dc77ee3f0182f377a6022b37cce590cab79205c497cfb964ee2d20","impliedFormat":99},{"version":"f320b8514d20e37f6b957334b715d79c9781baf54fda8f9192c1dc38e16d449b","signature":"bb7529605ce5ea3a70da2155f39510884954a39abd51cf787eb8a303f1e3ca5d"},{"version":"8404c6b0cd89fd85702086ab27d550099cc9ccb1b6670fc6484da5efe71c3c41","signature":"3e18169106207e83a0a2bc59e357d1473584a83a25641474f105ab56fd9490b3"},{"version":"1bcd560deed90a43c51b08aa18f7f55229f2e30974ab5ed1b7bb5721be379013","impliedFormat":99},{"version":"74012d464fbc5354ca3a7d5e71bee43b17da01a853c8ff10971bbe3680c76f40","impliedFormat":99},{"version":"5e30131b6a5587fe666926ad1d9807e733c0a597ed12d682669fcaa331aea576","impliedFormat":99},{"version":"a0f82d2f9450bd147a8c137798d9501bd49b7c9e118f75b07b76709ff39b6b55","affectsGlobalScope":true,"impliedFormat":99},{"version":"9a318e3a8900672b85cd3c8c3a5acf51b88049557a3ae897ccdcf2b85a8f61f9","impliedFormat":99},{"version":"dc08fe04e50bc24d1baded4f33e942222bbdd5d77d6341a93cfe6e4e4586a3be","impliedFormat":99},{"version":"00355f69398fa5d25778aefb29561e3718687fb930308c7b25bf40d951592152","signature":"06c27bacf3b20a46a0702910aff8d9ad4817681d7b3e14f450f856ba78ea7f76"},{"version":"cdeae34aca6700620ebf3f27cf7d439c3af97595dd6e2729fa4780483add5680","impliedFormat":99},{"version":"3ff87ea3471b51beaf4aa8fd8f4422862b11d343fdbb55bf383e0f8cc195a445","impliedFormat":99},{"version":"2d8757dd5fdb0b2f6c09f327d14f854202db1e3c0abf3e5d35c071055d167b92","signature":"0e50c13d260e97a5961bd202fe17232fb0301f668c3ba420beeecd213b0005e9"},{"version":"3e42659da436c840334cf9e989ab14009e5d3f5f62f75633d1d906c57f8634ab","signature":"a1ffd1c477e4c44624597d5a4232a6f4dc42dcda9f9b74ab2ff85f1819a95f18"},{"version":"99bdf729529cdbf12e2bf76ea751b662011133dcf9e35abcb3def47bb02f7b0a","impliedFormat":99},{"version":"e3ae5966ff412fa4b84b44359d356282194623750eadd8e3e20c0763efc6c811","signature":"f0223b66a3c156c00a5815a5853cbaf830636dc53bd6c328ee8389be92eec8e6"},{"version":"7455f2d44bbd248413e4ab8c3ff847413d9ce327967dba66f0b51880f60fb653","impliedFormat":99},{"version":"9dd82c87281e106bdcb227550251fcc6b55a6eb555152bec5c6ce408345ffc57","affectsGlobalScope":true,"impliedFormat":99},{"version":"38df32d74f5cb92d08a7ace088d631e65fd4ae41fd1098ef74ad8efab03763ac","impliedFormat":99},{"version":"ff169075cb4df455eaa1dc4972416ae6981adca96429ed698a306da3d5a2e241","impliedFormat":99},{"version":"5dd01302b91c8fb2aea381396623c5463c47a41c1b5d675672a075c5d8aa164c","affectsGlobalScope":true,"impliedFormat":99},{"version":"f3731eb0da8be50797a04467e9021082654c55d6cbabaf17a9d505c0ff3033cc","impliedFormat":99},{"version":"6146b370459b8f7e81f61b7dd9022fb06509cc20d34514dc782c9ce538fd8ec9","impliedFormat":99},{"version":"a585baba6d92b7f5052a11c3a5d0bcc73657180bb6066cf70e1b4664df4e8363","impliedFormat":99},{"version":"1aacab8ad3bd52a3a508b9c07bb341d680448fc9ee45591708ded8113c1be517","impliedFormat":99},{"version":"375ccf781ce7f845db6d13839e6085e520dac2a024679528229823d402ba1edc","signature":"4d4573b5fe4e0012638e5faaf0d8f77365359ce60cde1b0bafc62f48400a7e3d"},{"version":"361aaaeedfa37b1da60c8017b07a9968062968f71561c479bc83944063f5804d","signature":"cc8929ab4c4e9be68dd16405c46e97463b36038700f49d070e2d24ee4139c87c"},{"version":"d719146ac4cda335a8e970ba5918cf154be98b83c6f4b3acb4c02f6617cd92f6","signature":"75f5083114303492bddf59e3b81debed86d2a422666bb2d7c69513ad64a61a26"},{"version":"348c8e833a387ff25bdec06826c01c364738982079c2ba1cb390847141721ad1","signature":"a19c051036e9cb67b13b0b536c2ea9c8a8444e8797ece8db8963abd141f05017"}],"root":[52,53,60,63,64,66,[76,79]],"options":{"allowImportingTsExtensions":false,"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":false,"experimentalDecorators":true,"inlineSources":true,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitOverride":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":7,"tsBuildInfoFile":"./.tsbuildinfo","useDefineForClassFields":false,"verbatimModuleSyntax":true},"referencedMap":[[75,1],[68,2],[69,3],[71,4],[74,3],[73,3],[70,5],[62,6],[65,7],[57,8],[58,9],[48,10],[51,11],[50,12],[59,13],[76,14],[77,15],[78,16],[79,17],[52,18],[60,19],[63,20],[66,21]],"latestChangedDtsFile":"./controllers/virtual-scroll.d.ts","version":"6.0.3"}
1
+ {"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/lit-html/development/directive.d.ts","../../../node_modules/@types/trusted-types/lib/index.d.ts","../../../node_modules/lit-html/development/lit-html.d.ts","../../../node_modules/lit-html/development/directives/class-map.d.ts","../src/css-helper.ts","../src/data-helper.ts","../../../node_modules/lit-html/development/is-server.d.ts","../../../node_modules/@lit/reactive-element/development/css-tag.d.ts","../../../node_modules/@lit/reactive-element/development/reactive-controller.d.ts","../../../node_modules/@lit/reactive-element/development/reactive-element.d.ts","../../../node_modules/lit-element/development/lit-element.d.ts","../../../node_modules/lit/development/index.d.ts","../src/dom-helper.ts","../../../node_modules/@lit/reactive-element/development/decorators/base.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/custom-element.d.ts","../src/element-helper.ts","../src/event-helper.ts","../../../node_modules/@lit/reactive-element/development/decorators/property.d.ts","../src/lit-helper.ts","../src/shortcut-helper.ts","../../../node_modules/@lit/context/development/lib/create-context.d.ts","../../../node_modules/@lit/context/development/lib/context-request-event.d.ts","../../../node_modules/@lit/context/development/lib/controllers/context-consumer.d.ts","../../../node_modules/@lit/context/development/lib/value-notifier.d.ts","../../../node_modules/@lit/context/development/lib/controllers/context-provider.d.ts","../../../node_modules/@lit/context/development/lib/context-root.d.ts","../../../node_modules/@lit/context/development/lib/decorators/provide.d.ts","../../../node_modules/@lit/context/development/lib/decorators/consume.d.ts","../../../node_modules/@lit/context/development/index.d.ts","../src/contexts/pager.ts","../src/controllers/breakpoints-observer.ts","../src/controllers/context-consumer.ts","../src/controllers/virtual-scroll.ts"],"fileIdsList":[[68,69,70,72,73,74,75],[68],[57,68],[57,68,69,71],[69],[61],[57,61],[55,56],[50,57],[50],[48,50],[48,49],[50,54,57,58],[76],[57],[57,76],[59],[51],[54,59],[54,62],[57,59,65]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"00cb63103f9670f8094c238a4a7e252c8b4c06ba371fea5c44add7e41b7247e4","impliedFormat":99},{"version":"15fe687c59d62741b4494d5e623d497d55eb38966ecf5bea7f36e48fc3fbe15e","impliedFormat":1},{"version":"e09db3291e6b440f7debed2227d8357e80c95987a0d0d67ac17521d8f7b11bdb","impliedFormat":99},{"version":"9e77270468dc77ee3f0182f377a6022b37cce590cab79205c497cfb964ee2d20","impliedFormat":99},{"version":"f320b8514d20e37f6b957334b715d79c9781baf54fda8f9192c1dc38e16d449b","signature":"bb7529605ce5ea3a70da2155f39510884954a39abd51cf787eb8a303f1e3ca5d"},{"version":"8404c6b0cd89fd85702086ab27d550099cc9ccb1b6670fc6484da5efe71c3c41","signature":"3e18169106207e83a0a2bc59e357d1473584a83a25641474f105ab56fd9490b3"},{"version":"1bcd560deed90a43c51b08aa18f7f55229f2e30974ab5ed1b7bb5721be379013","impliedFormat":99},{"version":"74012d464fbc5354ca3a7d5e71bee43b17da01a853c8ff10971bbe3680c76f40","impliedFormat":99},{"version":"5e30131b6a5587fe666926ad1d9807e733c0a597ed12d682669fcaa331aea576","impliedFormat":99},{"version":"a0f82d2f9450bd147a8c137798d9501bd49b7c9e118f75b07b76709ff39b6b55","affectsGlobalScope":true,"impliedFormat":99},{"version":"9a318e3a8900672b85cd3c8c3a5acf51b88049557a3ae897ccdcf2b85a8f61f9","impliedFormat":99},{"version":"dc08fe04e50bc24d1baded4f33e942222bbdd5d77d6341a93cfe6e4e4586a3be","impliedFormat":99},{"version":"00355f69398fa5d25778aefb29561e3718687fb930308c7b25bf40d951592152","signature":"06c27bacf3b20a46a0702910aff8d9ad4817681d7b3e14f450f856ba78ea7f76"},{"version":"cdeae34aca6700620ebf3f27cf7d439c3af97595dd6e2729fa4780483add5680","impliedFormat":99},{"version":"3ff87ea3471b51beaf4aa8fd8f4422862b11d343fdbb55bf383e0f8cc195a445","impliedFormat":99},{"version":"5bac68e8ed6b3f45c75c2ada20ef7d292401611bbbcb945475529e02e0e90666","signature":"987fdd15284a3e71a0fcb58c8cdb8a82e51227f9ba90edccf57f10bc7c7722dc"},{"version":"3e42659da436c840334cf9e989ab14009e5d3f5f62f75633d1d906c57f8634ab","signature":"a1ffd1c477e4c44624597d5a4232a6f4dc42dcda9f9b74ab2ff85f1819a95f18"},{"version":"99bdf729529cdbf12e2bf76ea751b662011133dcf9e35abcb3def47bb02f7b0a","impliedFormat":99},{"version":"e3ae5966ff412fa4b84b44359d356282194623750eadd8e3e20c0763efc6c811","signature":"f0223b66a3c156c00a5815a5853cbaf830636dc53bd6c328ee8389be92eec8e6"},{"version":"d313896abf823dc5acd6691234f3c1ac40ec2c332443cb2ca79327aa333f7c94","signature":"ac455106204d69c0399018dc4a8fa48714e8e2c21ca294bfc793ad522ff67146"},{"version":"7455f2d44bbd248413e4ab8c3ff847413d9ce327967dba66f0b51880f60fb653","impliedFormat":99},{"version":"9dd82c87281e106bdcb227550251fcc6b55a6eb555152bec5c6ce408345ffc57","affectsGlobalScope":true,"impliedFormat":99},{"version":"38df32d74f5cb92d08a7ace088d631e65fd4ae41fd1098ef74ad8efab03763ac","impliedFormat":99},{"version":"ff169075cb4df455eaa1dc4972416ae6981adca96429ed698a306da3d5a2e241","impliedFormat":99},{"version":"5dd01302b91c8fb2aea381396623c5463c47a41c1b5d675672a075c5d8aa164c","affectsGlobalScope":true,"impliedFormat":99},{"version":"f3731eb0da8be50797a04467e9021082654c55d6cbabaf17a9d505c0ff3033cc","impliedFormat":99},{"version":"6146b370459b8f7e81f61b7dd9022fb06509cc20d34514dc782c9ce538fd8ec9","impliedFormat":99},{"version":"a585baba6d92b7f5052a11c3a5d0bcc73657180bb6066cf70e1b4664df4e8363","impliedFormat":99},{"version":"1aacab8ad3bd52a3a508b9c07bb341d680448fc9ee45591708ded8113c1be517","impliedFormat":99},{"version":"375ccf781ce7f845db6d13839e6085e520dac2a024679528229823d402ba1edc","signature":"4d4573b5fe4e0012638e5faaf0d8f77365359ce60cde1b0bafc62f48400a7e3d"},{"version":"361aaaeedfa37b1da60c8017b07a9968062968f71561c479bc83944063f5804d","signature":"cc8929ab4c4e9be68dd16405c46e97463b36038700f49d070e2d24ee4139c87c"},{"version":"d719146ac4cda335a8e970ba5918cf154be98b83c6f4b3acb4c02f6617cd92f6","signature":"75f5083114303492bddf59e3b81debed86d2a422666bb2d7c69513ad64a61a26"},{"version":"348c8e833a387ff25bdec06826c01c364738982079c2ba1cb390847141721ad1","signature":"a19c051036e9cb67b13b0b536c2ea9c8a8444e8797ece8db8963abd141f05017"}],"root":[52,53,60,63,64,66,67,[77,80]],"options":{"allowImportingTsExtensions":false,"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":false,"experimentalDecorators":true,"inlineSources":true,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitOverride":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":7,"tsBuildInfoFile":"./.tsbuildinfo","useDefineForClassFields":false,"verbatimModuleSyntax":true},"referencedMap":[[76,1],[69,2],[70,3],[72,4],[75,3],[74,3],[71,5],[62,6],[65,7],[57,8],[58,9],[48,10],[51,11],[50,12],[59,13],[77,14],[78,15],[79,16],[80,17],[52,18],[60,19],[63,20],[66,21]],"latestChangedDtsFile":"./controllers/virtual-scroll.d.ts","version":"6.0.3"}
@@ -8,7 +8,8 @@ import { type CustomElementDecorator } from '@lit/reactive-element/decorators/cu
8
8
  * warning leaves the page working; the element still behaves like whichever copy won the race.
9
9
  *
10
10
  * It also forwards the lowercased spelling of a camelCase attribute to the real one, with a warning (see
11
- * {@link installAttributeCheck}).
11
+ * {@link installAttributeCheck}), and keeps reflected properties that still hold their default off the host (see
12
+ * {@link keepDefaultsOffTheHost}).
12
13
  */
13
14
  export declare const customElement: (tagName: string) => CustomElementDecorator;
14
15
  //# sourceMappingURL=element-helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"element-helper.d.ts","sourceRoot":"","sources":["../src/element-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,sBAAsB,EAAE,MAAM,oDAAoD,CAAA;AAsEnI;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GACvB,SAAS,MAAM,KAAG,sBAelB,CAAA"}
1
+ {"version":3,"file":"element-helper.d.ts","sourceRoot":"","sources":["../src/element-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,sBAAsB,EAAE,MAAM,oDAAoD,CAAA;AAiJnI;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GACvB,SAAS,MAAM,KAAG,sBAkBlB,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { customElement as litCustomElement } from '@lit/reactive-element/decorators/custom-element.js';
2
+ import { isServer } from 'lit-html/is-server.js';
2
3
  const warned = new Set();
3
4
  function warnOnce(key, message) {
4
5
  if (warned.has(key))
@@ -52,6 +53,74 @@ function installAttributeCheck(tagName, elementClass) {
52
53
  }
53
54
  };
54
55
  }
56
+ const reflectedByClass = new WeakMap();
57
+ /** Attribute name → property name, for every property declared with `reflect: true`. Read once per class. */
58
+ function reflectedAttributes(elementClass) {
59
+ const cached = reflectedByClass.get(elementClass);
60
+ if (cached)
61
+ return cached;
62
+ const reflected = new Map();
63
+ reflectedByClass.set(elementClass, reflected);
64
+ for (const [name, declaration] of elementClass.elementProperties ?? []) {
65
+ if (!declaration.reflect || declaration.attribute === false)
66
+ continue;
67
+ reflected.set(typeof declaration.attribute === 'string' ? declaration.attribute : String(name).toLowerCase(), name);
68
+ }
69
+ return reflected;
70
+ }
71
+ /** The value each reflected property held when construction finished: the class-field defaults. */
72
+ const constructedDefaults = new WeakMap();
73
+ /** Hosts inside `update()`, which is where Lit reflects properties to attributes. */
74
+ const updatingHosts = new WeakSet();
75
+ /**
76
+ * Subclasses a component so Lit does not reflect a property that still holds its class-field default onto an
77
+ * attribute the host does not have.
78
+ *
79
+ * Lit reflects every `reflect: true` property on the first update, defaults included, so a bare `<c2-button>` gains
80
+ * `type="button" name=""` the moment it upgrades. Under SSR (Next.js, React Router) that happens before React
81
+ * hydrates, and React reports each of those attributes as a hydration mismatch. Keeping defaults off the host means
82
+ * an element's attributes are the ones its author wrote, plus the values that were actually changed.
83
+ *
84
+ * The consequence for styling: a default value is not visible as an attribute, so `:host([size='m'])` does not
85
+ * match a host that never had `size` set. Write default-state rules against the attribute's absence
86
+ * (`:host(:not([size]))`), or not against the attribute at all.
87
+ *
88
+ * A value set after construction — by the author, a framework or the component itself — reflects as before, and an
89
+ * attribute the host already carries keeps being updated, so it never goes stale. The class needs a subclass
90
+ * because the defaults are only known once the component's own constructor, which assigns them, has returned.
91
+ */
92
+ function keepDefaultsOffTheHost(target) {
93
+ const Base = target;
94
+ class DefaultsOffTheHost extends Base {
95
+ constructor(...args) {
96
+ super(...args);
97
+ const reflected = reflectedAttributes(this.constructor);
98
+ if (reflected.size)
99
+ constructedDefaults.set(this, new Map([...reflected.values()].map((property) => [property, this[property]])));
100
+ }
101
+ update(changedProperties) {
102
+ updatingHosts.add(this);
103
+ try {
104
+ super.update(changedProperties);
105
+ }
106
+ finally {
107
+ updatingHosts.delete(this);
108
+ }
109
+ }
110
+ setAttribute(name, value) {
111
+ if (!isServer && updatingHosts.has(this) && !this.hasAttribute(name)) {
112
+ const defaults = constructedDefaults.get(this);
113
+ const property = reflectedAttributes(this.constructor).get(name);
114
+ if (defaults && property !== undefined && defaults.has(property) && Object.is(this[property], defaults.get(property)))
115
+ return;
116
+ }
117
+ super.setAttribute(name, value);
118
+ }
119
+ }
120
+ // Keep the component's own name in stack traces and devtools.
121
+ Object.defineProperty(DefaultsOffTheHost, 'name', { value: target.name });
122
+ return DefaultsOffTheHost;
123
+ }
55
124
  /**
56
125
  * `@customElement`, but a duplicate registration warns instead of throwing.
57
126
  *
@@ -61,7 +130,8 @@ function installAttributeCheck(tagName, elementClass) {
61
130
  * warning leaves the page working; the element still behaves like whichever copy won the race.
62
131
  *
63
132
  * It also forwards the lowercased spelling of a camelCase attribute to the real one, with a warning (see
64
- * {@link installAttributeCheck}).
133
+ * {@link installAttributeCheck}), and keeps reflected properties that still hold their default off the host (see
134
+ * {@link keepDefaultsOffTheHost}).
65
135
  */
66
136
  export const customElement = (tagName) => (target, context) => {
67
137
  installAttributeCheck(tagName, target);
@@ -69,8 +139,11 @@ export const customElement = (tagName) => (target, context) => {
69
139
  warnOnce(`define:${tagName}`, `<${tagName}> is already registered. The first definition is kept; this one is ignored. Two copies of a @c2n package are loaded — check for duplicate versions in the dependency tree.`);
70
140
  return;
71
141
  }
72
- // `context` is `undefined` under experimental decorators and a `ClassDecoratorContext` under standard ones;
73
- // Lit's decorator handles both, so it is forwarded exactly as received.
74
- return litCustomElement(tagName)(target, context);
142
+ // The subclass is what gets registered, and returning it replaces the decorated class binding, so the exported
143
+ // class and the registered one stay the same. `context` is `undefined` under experimental decorators and a
144
+ // `ClassDecoratorContext` under standard ones; Lit's decorator handles both, so it is forwarded as received.
145
+ const element = keepDefaultsOffTheHost(target);
146
+ litCustomElement(tagName)(element, context);
147
+ return element;
75
148
  };
76
149
  //# sourceMappingURL=element-helper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"element-helper.js","sourceRoot":"","sources":["../src/element-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAA+B,MAAM,oDAAoD,CAAA;AAanI,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;AAEhC,SAAS,QAAQ,CAAC,GAAW,EAAE,OAAe;IAC5C,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAM;IAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACf,OAAO,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAA;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,mBAAmB,CAAC,YAAsC;IACjE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,YAAY,CAAC,iBAAiB,IAAI,EAAE,EAAE,CAAC;QACvE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,WAAW,CAAC,SAAS,KAAK,KAAK;YAAE,SAAQ;QACzE,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;QACxG,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACrC,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAClE,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,OAAe,EAAE,YAAsC;IACpF,MAAM,SAAS,GAAG,YAAY,CAAC,SAA6D,CAAA;IAC5F,MAAM,SAAS,GAAG,SAAS,CAAC,iBAAiB,CAAA;IAC7C,IAAI,OAAwC,CAAA;IAE5C,SAAS,CAAC,iBAAiB,GAAG;QAC5B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QAErB,oGAAoG;QACpG,OAAO,KAAP,OAAO,GAAK,mBAAmB,CAAC,YAAY,CAAC,EAAA;QAC7C,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YAAE,OAAM;QAEvD,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACnD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACnC,IAAI,CAAC,SAAS;gBAAE,SAAQ;YACxB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;gBAAE,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YACtE,QAAQ,CACN,GAAG,OAAO,IAAI,IAAI,EAAE,EACpB,IAAI,OAAO,IAAI,IAAI,2DAA2D,SAAS,4CAA4C,SAAS,2BAA2B,CACxK,CAAA;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GACxB,CAAC,OAAe,EAA0B,EAAE,CAC5C,CAAC,MAAoB,EAAE,OAA+B,EAAE,EAAE;IACxD,qBAAqB,CAAC,OAAO,EAAE,MAAkC,CAAC,CAAA;IAElE,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,QAAQ,CACN,UAAU,OAAO,EAAE,EACnB,IAAI,OAAO,4KAA4K,CACxL,CAAA;QACD,OAAM;IACR,CAAC;IAED,4GAA4G;IAC5G,wEAAwE;IACxE,OAAQ,gBAAgB,CAAC,OAAO,CAAqE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AACxH,CAAC,CAAA","sourcesContent":["import { customElement as litCustomElement, type CustomElementDecorator } from '@lit/reactive-element/decorators/custom-element.js'\n\ntype ElementClass = Omit<typeof HTMLElement, 'new'>\n\ninterface PropertyDeclarationLike {\n attribute?: boolean | string\n}\n\ninterface ReactiveElementClassLike extends ElementClass {\n elementProperties?: Map<PropertyKey, PropertyDeclarationLike>\n prototype: HTMLElement\n}\n\nconst warned = new Set<string>()\n\nfunction warnOnce(key: string, message: string): void {\n if (warned.has(key)) return\n warned.add(key)\n console.warn(`[c2n] ${message}`)\n}\n\n/**\n * Attributes a consumer is likely to write instead of the real one: the lowercased spelling of a camelCase\n * property whose attribute was renamed to kebab-case (`rowkey` for `rowKey`, whose attribute is `row-key`).\n *\n * The lowercased spelling is what a framework produces from a *static* attribute in a template — Angular and\n * plain HTML both do it, and so does React when it renders a custom element on the server (the prop name is\n * written verbatim and the parser lowercases it; hydration never sets the property). The component does not\n * observe it, so without help the value is silently dropped.\n */\nfunction ambiguousAttributes(elementClass: ReactiveElementClassLike): Map<string, string> {\n const aliases = new Map<string, string>()\n for (const [name, declaration] of elementClass.elementProperties ?? []) {\n if (typeof name !== 'string' || declaration.attribute === false) continue\n const attribute = typeof declaration.attribute === 'string' ? declaration.attribute : name.toLowerCase()\n const lowercased = name.toLowerCase()\n if (lowercased !== attribute) aliases.set(lowercased, attribute)\n }\n return aliases\n}\n\n/**\n * Forwards the lowercased spelling of a camelCase property to the attribute the component observes, and warns\n * once per tag and attribute so the author can fix the template. The real attribute wins when both are present.\n * Installed by {@link customElement} and skipped entirely for components that have none.\n */\nfunction installAttributeCheck(tagName: string, elementClass: ReactiveElementClassLike): void {\n const prototype = elementClass.prototype as HTMLElement & { connectedCallback?: () => void }\n const connected = prototype.connectedCallback\n let aliases: Map<string, string> | undefined\n\n prototype.connectedCallback = function (this: HTMLElement) {\n connected?.call(this)\n\n // Resolved on the first connect: `elementProperties` is only complete once every decorator has run.\n aliases ??= ambiguousAttributes(elementClass)\n if (aliases.size === 0 || !this.hasAttributes()) return\n\n for (const { name, value } of [...this.attributes]) {\n const attribute = aliases.get(name)\n if (!attribute) continue\n if (!this.hasAttribute(attribute)) this.setAttribute(attribute, value)\n warnOnce(\n `${tagName}:${name}`,\n `<${tagName} ${name}> is not an attribute of this component — did you mean \"${attribute}\"? The value was forwarded to it; write \"${attribute}\" so it is read directly.`,\n )\n }\n }\n}\n\n/**\n * `@customElement`, but a duplicate registration warns instead of throwing.\n *\n * `customElements.define` throws `NotSupportedError` when a tag is already taken, which takes down the whole\n * page. That happens for reasons a component library cannot control: two versions of a package in one app, two\n * micro-frontends, a module graph loaded twice, a dev server's hot reload. Keeping the first definition and\n * warning leaves the page working; the element still behaves like whichever copy won the race.\n *\n * It also forwards the lowercased spelling of a camelCase attribute to the real one, with a warning (see\n * {@link installAttributeCheck}).\n */\nexport const customElement =\n (tagName: string): CustomElementDecorator =>\n (target: ElementClass, context?: ClassDecoratorContext) => {\n installAttributeCheck(tagName, target as ReactiveElementClassLike)\n\n if (customElements.get(tagName)) {\n warnOnce(\n `define:${tagName}`,\n `<${tagName}> is already registered. The first definition is kept; this one is ignored. Two copies of a @c2n package are loaded — check for duplicate versions in the dependency tree.`,\n )\n return\n }\n\n // `context` is `undefined` under experimental decorators and a `ClassDecoratorContext` under standard ones;\n // Lit's decorator handles both, so it is forwarded exactly as received.\n return (litCustomElement(tagName) as (target: ElementClass, context?: ClassDecoratorContext) => void)(target, context)\n }\n"]}
1
+ {"version":3,"file":"element-helper.js","sourceRoot":"","sources":["../src/element-helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { customElement as litCustomElement, type CustomElementDecorator } from '@lit/reactive-element/decorators/custom-element.js'\nimport { isServer } from 'lit-html/is-server.js'\n\ntype ElementClass = Omit<typeof HTMLElement, 'new'>\n\ninterface PropertyDeclarationLike {\n attribute?: boolean | string\n reflect?: boolean\n}\n\ninterface ReactiveElementClassLike extends ElementClass {\n elementProperties?: Map<PropertyKey, PropertyDeclarationLike>\n prototype: HTMLElement\n}\n\nconst warned = new Set<string>()\n\nfunction warnOnce(key: string, message: string): void {\n if (warned.has(key)) return\n warned.add(key)\n console.warn(`[c2n] ${message}`)\n}\n\n/**\n * Attributes a consumer is likely to write instead of the real one: the lowercased spelling of a camelCase\n * property whose attribute was renamed to kebab-case (`rowkey` for `rowKey`, whose attribute is `row-key`).\n *\n * The lowercased spelling is what a framework produces from a *static* attribute in a template — Angular and\n * plain HTML both do it, and so does React when it renders a custom element on the server (the prop name is\n * written verbatim and the parser lowercases it; hydration never sets the property). The component does not\n * observe it, so without help the value is silently dropped.\n */\nfunction ambiguousAttributes(elementClass: ReactiveElementClassLike): Map<string, string> {\n const aliases = new Map<string, string>()\n for (const [name, declaration] of elementClass.elementProperties ?? []) {\n if (typeof name !== 'string' || declaration.attribute === false) continue\n const attribute = typeof declaration.attribute === 'string' ? declaration.attribute : name.toLowerCase()\n const lowercased = name.toLowerCase()\n if (lowercased !== attribute) aliases.set(lowercased, attribute)\n }\n return aliases\n}\n\n/**\n * Forwards the lowercased spelling of a camelCase property to the attribute the component observes, and warns\n * once per tag and attribute so the author can fix the template. The real attribute wins when both are present.\n * Installed by {@link customElement} and skipped entirely for components that have none.\n */\nfunction installAttributeCheck(tagName: string, elementClass: ReactiveElementClassLike): void {\n const prototype = elementClass.prototype as HTMLElement & { connectedCallback?: () => void }\n const connected = prototype.connectedCallback\n let aliases: Map<string, string> | undefined\n\n prototype.connectedCallback = function (this: HTMLElement) {\n connected?.call(this)\n\n // Resolved on the first connect: `elementProperties` is only complete once every decorator has run.\n aliases ??= ambiguousAttributes(elementClass)\n if (aliases.size === 0 || !this.hasAttributes()) return\n\n for (const { name, value } of [...this.attributes]) {\n const attribute = aliases.get(name)\n if (!attribute) continue\n if (!this.hasAttribute(attribute)) this.setAttribute(attribute, value)\n warnOnce(\n `${tagName}:${name}`,\n `<${tagName} ${name}> is not an attribute of this component — did you mean \"${attribute}\"? The value was forwarded to it; write \"${attribute}\" so it is read directly.`,\n )\n }\n }\n}\n\nconst reflectedByClass = new WeakMap<object, Map<string, PropertyKey>>()\n\n/** Attribute name → property name, for every property declared with `reflect: true`. Read once per class. */\nfunction reflectedAttributes(elementClass: ReactiveElementClassLike): Map<string, PropertyKey> {\n const cached = reflectedByClass.get(elementClass)\n if (cached) return cached\n const reflected = new Map<string, PropertyKey>()\n reflectedByClass.set(elementClass, reflected)\n for (const [name, declaration] of elementClass.elementProperties ?? []) {\n if (!declaration.reflect || declaration.attribute === false) continue\n reflected.set(typeof declaration.attribute === 'string' ? declaration.attribute : String(name).toLowerCase(), name)\n }\n return reflected\n}\n\ntype ReflectingHost = HTMLElement & Record<PropertyKey, unknown> & { update(changedProperties: unknown): void }\n\n/** The value each reflected property held when construction finished: the class-field defaults. */\nconst constructedDefaults = new WeakMap<HTMLElement, Map<PropertyKey, unknown>>()\n/** Hosts inside `update()`, which is where Lit reflects properties to attributes. */\nconst updatingHosts = new WeakSet<HTMLElement>()\n\n/**\n * Subclasses a component so Lit does not reflect a property that still holds its class-field default onto an\n * attribute the host does not have.\n *\n * Lit reflects every `reflect: true` property on the first update, defaults included, so a bare `<c2-button>` gains\n * `type=\"button\" name=\"\"` the moment it upgrades. Under SSR (Next.js, React Router) that happens before React\n * hydrates, and React reports each of those attributes as a hydration mismatch. Keeping defaults off the host means\n * an element's attributes are the ones its author wrote, plus the values that were actually changed.\n *\n * The consequence for styling: a default value is not visible as an attribute, so `:host([size='m'])` does not\n * match a host that never had `size` set. Write default-state rules against the attribute's absence\n * (`:host(:not([size]))`), or not against the attribute at all.\n *\n * A value set after construction — by the author, a framework or the component itself — reflects as before, and an\n * attribute the host already carries keeps being updated, so it never goes stale. The class needs a subclass\n * because the defaults are only known once the component's own constructor, which assigns them, has returned.\n */\nfunction keepDefaultsOffTheHost(target: ElementClass): ElementClass {\n const Base = target as unknown as new (...args: unknown[]) => ReflectingHost\n\n class DefaultsOffTheHost extends Base {\n constructor(...args: unknown[]) {\n super(...args)\n const reflected = reflectedAttributes(this.constructor as unknown as ReactiveElementClassLike)\n if (reflected.size) constructedDefaults.set(this, new Map([...reflected.values()].map((property) => [property, this[property]])))\n }\n\n override update(changedProperties: unknown): void {\n updatingHosts.add(this)\n try {\n super.update(changedProperties)\n } finally {\n updatingHosts.delete(this)\n }\n }\n\n override setAttribute(name: string, value: string): void {\n if (!isServer && updatingHosts.has(this) && !this.hasAttribute(name)) {\n const defaults = constructedDefaults.get(this)\n const property = reflectedAttributes(this.constructor as unknown as ReactiveElementClassLike).get(name)\n if (defaults && property !== undefined && defaults.has(property) && Object.is(this[property], defaults.get(property))) return\n }\n super.setAttribute(name, value)\n }\n }\n\n // Keep the component's own name in stack traces and devtools.\n Object.defineProperty(DefaultsOffTheHost, 'name', { value: (target as unknown as { name: string }).name })\n return DefaultsOffTheHost as unknown as ElementClass\n}\n\n/**\n * `@customElement`, but a duplicate registration warns instead of throwing.\n *\n * `customElements.define` throws `NotSupportedError` when a tag is already taken, which takes down the whole\n * page. That happens for reasons a component library cannot control: two versions of a package in one app, two\n * micro-frontends, a module graph loaded twice, a dev server's hot reload. Keeping the first definition and\n * warning leaves the page working; the element still behaves like whichever copy won the race.\n *\n * It also forwards the lowercased spelling of a camelCase attribute to the real one, with a warning (see\n * {@link installAttributeCheck}), and keeps reflected properties that still hold their default off the host (see\n * {@link keepDefaultsOffTheHost}).\n */\nexport const customElement =\n (tagName: string): CustomElementDecorator =>\n (target: ElementClass, context?: ClassDecoratorContext) => {\n installAttributeCheck(tagName, target as ReactiveElementClassLike)\n\n if (customElements.get(tagName)) {\n warnOnce(\n `define:${tagName}`,\n `<${tagName}> is already registered. The first definition is kept; this one is ignored. Two copies of a @c2n package are loaded — check for duplicate versions in the dependency tree.`,\n )\n return\n }\n\n // The subclass is what gets registered, and returning it replaces the decorated class binding, so the exported\n // class and the registered one stay the same. `context` is `undefined` under experimental decorators and a\n // `ClassDecoratorContext` under standard ones; Lit's decorator handles both, so it is forwarded as received.\n const element = keepDefaultsOffTheHost(target)\n ;(litCustomElement(tagName) as (target: ElementClass, context?: ClassDecoratorContext) => void)(element, context)\n return element\n }\n"]}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Keyboard shortcuts: parse the `mod+k, mod+k mod+s` syntax, match it against `keydown` events, format it for display
3
+ * and for `aria-keyshortcuts`, and route every registered binding through one shared document listener.
4
+ *
5
+ * Syntax. A binding's `keys` is a comma-separated list of alternatives; an alternative is a space-separated
6
+ * sequence of strokes; a stroke is `+`-joined modifiers followed by one key. `mod` is ⌘ on Apple platforms and
7
+ * Ctrl elsewhere. Key names are `KeyboardEvent.key` values, case-insensitive, plus the aliases in {@link KEY_ALIASES}
8
+ * (`esc`, `space`, `up`, `plus`, `comma`, …) for keys the syntax itself uses.
9
+ *
10
+ * Every stroke must be composed: it holds Ctrl, ⌘ or Alt (Shift alone does not count, `shift+a` is typing). Escape
11
+ * and the function keys F1–F24 are the only keys accepted on their own. An alternative with a bare stroke (`/`,
12
+ * `g d`) is dropped with a console warning.
13
+ *
14
+ * mod+k ⌘K / Ctrl+K
15
+ * mod+k, alt+/ either of two shortcuts
16
+ * mod+k mod+s ⌘K, then ⌘S within a second
17
+ * ctrl+shift+p all three modifiers must match, and no other
18
+ * escape, f1 keys that need no modifier
19
+ */
20
+ export interface ShortcutStroke {
21
+ /** Lowercased `KeyboardEvent.key` (after aliasing). */
22
+ key: string;
23
+ ctrl: boolean;
24
+ meta: boolean;
25
+ alt: boolean;
26
+ shift: boolean;
27
+ /** `mod` was written: resolves to `meta` on Apple platforms and `ctrl` elsewhere. */
28
+ mod: boolean;
29
+ }
30
+ /** One alternative of a binding: the strokes pressed in order, and the text it was parsed from. */
31
+ export interface ShortcutSequence {
32
+ source: string;
33
+ strokes: ShortcutStroke[];
34
+ }
35
+ /** The options of a binding the shared listener reads. Components extend this with their own fields. */
36
+ export interface ShortcutBindingOptions {
37
+ keys: string;
38
+ /** `global` (default), `parent` (the registering element's parent) or a CSS selector matched against the focus path. */
39
+ scope?: string;
40
+ /** Fire even while focus is in an editable field. Strokes with Ctrl, ⌘ or Alt fire there regardless. */
41
+ allowInInputs?: boolean;
42
+ /** Leave the browser's own handling of the key alone instead of calling `preventDefault()`. */
43
+ allowDefault?: boolean;
44
+ /** Fire again for auto-repeated `keydown` events while the key is held. */
45
+ repeat?: boolean;
46
+ disabled?: boolean;
47
+ }
48
+ export interface ShortcutMatch<B extends ShortcutBindingOptions = ShortcutBindingOptions> {
49
+ binding: B;
50
+ /** The alternative that matched, as written (`alt+/` of `mod+k, alt+/`). */
51
+ keys: string;
52
+ event: KeyboardEvent;
53
+ }
54
+ /** Delay allowed between two strokes of a sequence. */
55
+ export declare const SEQUENCE_TIMEOUT = 1000;
56
+ export declare const KEY_ALIASES: Readonly<Record<string, string>>;
57
+ export declare function isApplePlatform(): boolean;
58
+ /** Whether a stroke is accepted: a chord, or Escape / a function key. */
59
+ export declare function isComposedStroke(stroke: ShortcutStroke): boolean;
60
+ /**
61
+ * Parses a `keys` string into its alternatives. Malformed alternatives (no key) and alternatives with a stroke that is
62
+ * not composed (see {@link isComposedStroke}) are dropped, the latter with a warning. The comma key has to be written
63
+ * `comma`, since a bare `,` separates alternatives.
64
+ */
65
+ export declare function parseShortcut(keys: string): ShortcutSequence[];
66
+ export declare function matchesStroke(stroke: ShortcutStroke, event: KeyboardEvent, apple?: boolean): boolean;
67
+ /**
68
+ * Human label for each alternative, in the platform's convention: `⌘K` / `⇧⌘P` on Apple platforms, `Ctrl+K` /
69
+ * `Ctrl+Shift+P` elsewhere. Strokes of a sequence are separated by a space (`G D`).
70
+ */
71
+ export declare function formatShortcut(keys: string, apple?: boolean): string[];
72
+ /**
73
+ * The `aria-keyshortcuts` value for a `keys` string (`Meta+K Control+K` style, one token per alternative). ARIA has
74
+ * no notation for a sequence, so multi-stroke alternatives are left out; an empty string means nothing to announce.
75
+ */
76
+ export declare function ariaKeyShortcuts(keys: string, apple?: boolean): string;
77
+ /** Whether a key event comes from a field the user types into (input, textarea, select, contenteditable). */
78
+ export declare function isEditableTarget(event: Event): boolean;
79
+ /**
80
+ * Registers `owner`'s bindings with the shared document listener and returns the function that unregisters them.
81
+ * `bindings` is read on every key press, so the owner can change its bindings without registering again. When
82
+ * several bindings match, the one scoped to the element closest to the focused node wins, then the one registered
83
+ * first. The listener calls `preventDefault()` on the key event (unless `allowDefault`) before `onMatch`.
84
+ */
85
+ export declare function registerShortcuts<B extends ShortcutBindingOptions>(owner: Element, bindings: () => readonly B[], onMatch: (match: ShortcutMatch<B>) => void): () => void;
86
+ //# sourceMappingURL=shortcut-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcut-helper.d.ts","sourceRoot":"","sources":["../src/shortcut-helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,GAAG,EAAE,OAAO,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,qFAAqF;IACrF,GAAG,EAAE,OAAO,CAAA;CACb;AAED,mGAAmG;AACnG,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,cAAc,EAAE,CAAA;CAC1B;AAED,wGAAwG;AACxG,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,wHAAwH;IACxH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wGAAwG;IACxG,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,+FAA+F;IAC/F,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,sBAAsB,GAAG,sBAAsB;IACtF,OAAO,EAAE,CAAC,CAAA;IACV,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,CAAA;CACrB;AAED,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,OAAO,CAAA;AAEpC,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAcxD,CAAA;AAID,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AA6BD,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAEhE;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAgB9D;AAaD,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,UAAoB,GAAG,OAAO,CAY9G;AA0CD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,UAAoB,GAAG,MAAM,EAAE,CAEhF;AAiBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,UAAoB,GAAG,MAAM,CAQhF;AAED,6GAA6G;AAC7G,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAMtD;AA8GD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,sBAAsB,EAChE,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,SAAS,CAAC,EAAE,EAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,GACzC,MAAM,IAAI,CAcZ"}
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Keyboard shortcuts: parse the `mod+k, mod+k mod+s` syntax, match it against `keydown` events, format it for display
3
+ * and for `aria-keyshortcuts`, and route every registered binding through one shared document listener.
4
+ *
5
+ * Syntax. A binding's `keys` is a comma-separated list of alternatives; an alternative is a space-separated
6
+ * sequence of strokes; a stroke is `+`-joined modifiers followed by one key. `mod` is ⌘ on Apple platforms and
7
+ * Ctrl elsewhere. Key names are `KeyboardEvent.key` values, case-insensitive, plus the aliases in {@link KEY_ALIASES}
8
+ * (`esc`, `space`, `up`, `plus`, `comma`, …) for keys the syntax itself uses.
9
+ *
10
+ * Every stroke must be composed: it holds Ctrl, ⌘ or Alt (Shift alone does not count, `shift+a` is typing). Escape
11
+ * and the function keys F1–F24 are the only keys accepted on their own. An alternative with a bare stroke (`/`,
12
+ * `g d`) is dropped with a console warning.
13
+ *
14
+ * mod+k ⌘K / Ctrl+K
15
+ * mod+k, alt+/ either of two shortcuts
16
+ * mod+k mod+s ⌘K, then ⌘S within a second
17
+ * ctrl+shift+p all three modifiers must match, and no other
18
+ * escape, f1 keys that need no modifier
19
+ */
20
+ /** Delay allowed between two strokes of a sequence. */
21
+ export const SEQUENCE_TIMEOUT = 1000;
22
+ export const KEY_ALIASES = {
23
+ esc: 'escape',
24
+ return: 'enter',
25
+ space: ' ',
26
+ spacebar: ' ',
27
+ up: 'arrowup',
28
+ down: 'arrowdown',
29
+ left: 'arrowleft',
30
+ right: 'arrowright',
31
+ del: 'delete',
32
+ ins: 'insert',
33
+ plus: '+',
34
+ comma: ',',
35
+ minus: '-',
36
+ };
37
+ const MODIFIER_KEYS = new Set(['control', 'meta', 'alt', 'shift', 'altgraph', 'os', 'capslock', 'fn']);
38
+ export function isApplePlatform() {
39
+ if (typeof navigator === 'undefined')
40
+ return false;
41
+ const platform = navigator.userAgentData?.platform ?? navigator.platform ?? '';
42
+ return /mac|iphone|ipad|ipod/i.test(platform);
43
+ }
44
+ function parseStroke(raw) {
45
+ // `+` separates parts, so a trailing `++` is the plus key itself (`ctrl++`); `plus` is the unambiguous spelling.
46
+ const parts = raw === '+' ? ['+'] : raw.endsWith('++') ? [...raw.slice(0, -2).split('+'), '+'] : raw.split('+');
47
+ const stroke = { key: '', ctrl: false, meta: false, alt: false, shift: false, mod: false };
48
+ for (const part of parts) {
49
+ const name = part.trim().toLowerCase();
50
+ if (!name)
51
+ continue;
52
+ if (name === 'mod')
53
+ stroke.mod = true;
54
+ else if (name === 'ctrl' || name === 'control')
55
+ stroke.ctrl = true;
56
+ else if (name === 'meta' || name === 'cmd' || name === 'command' || name === 'super')
57
+ stroke.meta = true;
58
+ else if (name === 'alt' || name === 'option' || name === 'opt')
59
+ stroke.alt = true;
60
+ else if (name === 'shift')
61
+ stroke.shift = true;
62
+ else
63
+ stroke.key = KEY_ALIASES[name] ?? name;
64
+ }
65
+ return stroke;
66
+ }
67
+ /** Whether the stroke holds Ctrl, ⌘ or Alt, the modifiers that make a key press a command rather than typing. */
68
+ function isChord(stroke) {
69
+ return stroke.ctrl || stroke.meta || stroke.alt || stroke.mod;
70
+ }
71
+ /** Keys that are commands on their own and need no modifier. */
72
+ function isStandaloneKey(key) {
73
+ return key === 'escape' || /^f([1-9]|1[0-9]|2[0-4])$/.test(key);
74
+ }
75
+ /** Whether a stroke is accepted: a chord, or Escape / a function key. */
76
+ export function isComposedStroke(stroke) {
77
+ return !!stroke.key && (isChord(stroke) || isStandaloneKey(stroke.key));
78
+ }
79
+ const cache = new Map();
80
+ /**
81
+ * Parses a `keys` string into its alternatives. Malformed alternatives (no key) and alternatives with a stroke that is
82
+ * not composed (see {@link isComposedStroke}) are dropped, the latter with a warning. The comma key has to be written
83
+ * `comma`, since a bare `,` separates alternatives.
84
+ */
85
+ export function parseShortcut(keys) {
86
+ const cached = cache.get(keys);
87
+ if (cached)
88
+ return cached;
89
+ const sequences = keys
90
+ .split(',')
91
+ .map((alternative) => alternative.trim())
92
+ .filter(Boolean)
93
+ .map((source) => ({ source, strokes: source.split(/\s+/).map(parseStroke) }))
94
+ .filter((sequence) => sequence.strokes.every((stroke) => stroke.key))
95
+ .filter((sequence) => {
96
+ if (sequence.strokes.every(isComposedStroke))
97
+ return true;
98
+ console.warn(`[c2-shortcut] "${sequence.source}" ignored: every key needs Ctrl, ⌘ or Alt (only Escape and F1–F24 may stand alone).`);
99
+ return false;
100
+ });
101
+ cache.set(keys, sequences);
102
+ return sequences;
103
+ }
104
+ function resolvedModifiers(stroke, apple) {
105
+ return { ctrl: stroke.ctrl || (stroke.mod && !apple), meta: stroke.meta || (stroke.mod && apple), alt: stroke.alt, shift: stroke.shift };
106
+ }
107
+ /** The physical key the stroke names, for layouts (and Option on macOS) where `event.key` is another character. */
108
+ function codeFor(key) {
109
+ if (/^[a-z]$/.test(key))
110
+ return `Key${key.toUpperCase()}`;
111
+ if (/^[0-9]$/.test(key))
112
+ return `Digit${key}`;
113
+ return undefined;
114
+ }
115
+ export function matchesStroke(stroke, event, apple = isApplePlatform()) {
116
+ const wanted = resolvedModifiers(stroke, apple);
117
+ if (event.ctrlKey !== wanted.ctrl || event.metaKey !== wanted.meta || event.altKey !== wanted.alt)
118
+ return false;
119
+ const key = (event.key ?? '').toLowerCase();
120
+ // A symbol such as `?` or `+` already implies whichever Shift state the layout needs to type it.
121
+ const symbol = key.length === 1 && !/[a-z0-9]/.test(key);
122
+ if (!(symbol && !wanted.shift) && event.shiftKey !== wanted.shift)
123
+ return false;
124
+ if (key === stroke.key)
125
+ return true;
126
+ // `event.key` is not plain ASCII (Option+K types `˚`, a Cyrillic layout types `л`, a dead key reads `Dead`):
127
+ // fall back to the physical key.
128
+ const ascii = key.length === 1 && key.charCodeAt(0) < 128;
129
+ return !ascii && event.code === codeFor(stroke.key);
130
+ }
131
+ const APPLE_KEY_LABELS = {
132
+ escape: 'Esc',
133
+ enter: '↵',
134
+ backspace: '⌫',
135
+ delete: '⌦',
136
+ tab: '⇥',
137
+ ' ': 'Space',
138
+ arrowup: '↑',
139
+ arrowdown: '↓',
140
+ arrowleft: '←',
141
+ arrowright: '→',
142
+ };
143
+ const KEY_LABELS = {
144
+ escape: 'Esc',
145
+ enter: 'Enter',
146
+ backspace: 'Backspace',
147
+ delete: 'Del',
148
+ tab: 'Tab',
149
+ ' ': 'Space',
150
+ arrowup: '↑',
151
+ arrowdown: '↓',
152
+ arrowleft: '←',
153
+ arrowright: '→',
154
+ };
155
+ function keyLabel(key, apple) {
156
+ const named = (apple ? APPLE_KEY_LABELS : KEY_LABELS)[key];
157
+ if (named)
158
+ return named;
159
+ if (key.length === 1)
160
+ return key.toUpperCase();
161
+ return key.charAt(0).toUpperCase() + key.slice(1);
162
+ }
163
+ function strokeLabel(stroke, apple) {
164
+ const { ctrl, meta, alt, shift } = resolvedModifiers(stroke, apple);
165
+ const key = keyLabel(stroke.key, apple);
166
+ if (apple)
167
+ return `${ctrl ? '⌃' : ''}${alt ? '⌥' : ''}${shift ? '⇧' : ''}${meta ? '⌘' : ''}${key}`;
168
+ return [ctrl && 'Ctrl', meta && 'Win', alt && 'Alt', shift && 'Shift', key].filter(Boolean).join('+');
169
+ }
170
+ /**
171
+ * Human label for each alternative, in the platform's convention: `⌘K` / `⇧⌘P` on Apple platforms, `Ctrl+K` /
172
+ * `Ctrl+Shift+P` elsewhere. Strokes of a sequence are separated by a space (`G D`).
173
+ */
174
+ export function formatShortcut(keys, apple = isApplePlatform()) {
175
+ return parseShortcut(keys).map((sequence) => sequence.strokes.map((stroke) => strokeLabel(stroke, apple)).join(' '));
176
+ }
177
+ const ARIA_KEY_NAMES = {
178
+ ' ': 'Space',
179
+ '+': 'Plus',
180
+ arrowup: 'ArrowUp',
181
+ arrowdown: 'ArrowDown',
182
+ arrowleft: 'ArrowLeft',
183
+ arrowright: 'ArrowRight',
184
+ pageup: 'PageUp',
185
+ pagedown: 'PageDown',
186
+ };
187
+ function ariaKeyName(key) {
188
+ return ARIA_KEY_NAMES[key] ?? (key.length === 1 ? key.toUpperCase() : key.charAt(0).toUpperCase() + key.slice(1));
189
+ }
190
+ /**
191
+ * The `aria-keyshortcuts` value for a `keys` string (`Meta+K Control+K` style, one token per alternative). ARIA has
192
+ * no notation for a sequence, so multi-stroke alternatives are left out; an empty string means nothing to announce.
193
+ */
194
+ export function ariaKeyShortcuts(keys, apple = isApplePlatform()) {
195
+ return parseShortcut(keys)
196
+ .filter((sequence) => sequence.strokes.length === 1)
197
+ .map(({ strokes: [stroke] }) => {
198
+ const { ctrl, meta, alt, shift } = resolvedModifiers(stroke, apple);
199
+ return [ctrl && 'Control', alt && 'Alt', shift && 'Shift', meta && 'Meta', ariaKeyName(stroke.key)].filter(Boolean).join('+');
200
+ })
201
+ .join(' ');
202
+ }
203
+ /** Whether a key event comes from a field the user types into (input, textarea, select, contenteditable). */
204
+ export function isEditableTarget(event) {
205
+ const target = event.composedPath()[0];
206
+ if (!(target instanceof HTMLElement))
207
+ return false;
208
+ if (target.isContentEditable || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement)
209
+ return true;
210
+ if (!(target instanceof HTMLInputElement))
211
+ return false;
212
+ return !['button', 'checkbox', 'color', 'file', 'image', 'radio', 'range', 'reset', 'submit'].includes(target.type);
213
+ }
214
+ const sources = [];
215
+ let pending = [];
216
+ let pendingTimer;
217
+ function clearPending() {
218
+ pending = [];
219
+ clearTimeout(pendingTimer);
220
+ pendingTimer = undefined;
221
+ }
222
+ function scopeDepth(source, scope, path) {
223
+ if (!scope || scope === 'global')
224
+ return Number.POSITIVE_INFINITY;
225
+ if (scope === 'parent') {
226
+ const parent = source.owner.parentNode;
227
+ const scopeElement = parent instanceof ShadowRoot ? parent.host : parent;
228
+ const index = scopeElement ? path.indexOf(scopeElement) : -1;
229
+ return index < 0 ? -1 : index;
230
+ }
231
+ try {
232
+ return path.findIndex((node) => node instanceof Element && node.matches(scope));
233
+ }
234
+ catch {
235
+ // An invalid selector scopes the binding to nothing rather than throwing on every key press.
236
+ return -1;
237
+ }
238
+ }
239
+ function eligibleCandidates(event) {
240
+ const path = event.composedPath();
241
+ const editable = isEditableTarget(event);
242
+ const candidates = [];
243
+ let order = 0;
244
+ for (const source of sources) {
245
+ for (const binding of source.bindings()) {
246
+ order += 1;
247
+ if (!binding || binding.disabled || typeof binding.keys !== 'string')
248
+ continue;
249
+ if (event.repeat && !binding.repeat)
250
+ continue;
251
+ const depth = scopeDepth(source, binding.scope, path);
252
+ if (depth < 0)
253
+ continue;
254
+ for (const sequence of parseShortcut(binding.keys)) {
255
+ if (editable && !binding.allowInInputs && !isChord(sequence.strokes[0]))
256
+ continue;
257
+ candidates.push({ source, binding, sequence, depth, order });
258
+ }
259
+ }
260
+ }
261
+ return candidates;
262
+ }
263
+ const byPriority = (a, b) => a.depth - b.depth || a.order - b.order;
264
+ function handleKeydown(event) {
265
+ // A pressed modifier on its own is part of the next stroke, not a stroke.
266
+ if (MODIFIER_KEYS.has((event.key ?? '').toLowerCase()))
267
+ return;
268
+ // A component that already handled the key (a list's arrow keys, a menu's typeahead) keeps it.
269
+ if (event.defaultPrevented) {
270
+ clearPending();
271
+ return;
272
+ }
273
+ const apple = isApplePlatform();
274
+ const candidates = eligibleCandidates(event);
275
+ const completed = [];
276
+ const advanced = [];
277
+ // Sequences already under way come first: after ⌘K, ⌘S completes `mod+k mod+s` rather than a lone `mod+s` binding.
278
+ for (const { candidate, progress } of pending) {
279
+ const still = candidates.find((c) => c.binding === candidate.binding && c.sequence === candidate.sequence);
280
+ if (!still || !matchesStroke(candidate.sequence.strokes[progress], event, apple))
281
+ continue;
282
+ if (progress + 1 === candidate.sequence.strokes.length)
283
+ completed.push(still);
284
+ else
285
+ advanced.push({ candidate: still, progress: progress + 1 });
286
+ }
287
+ if (!completed.length) {
288
+ for (const candidate of candidates) {
289
+ if (!matchesStroke(candidate.sequence.strokes[0], event, apple))
290
+ continue;
291
+ if (candidate.sequence.strokes.length === 1)
292
+ completed.push(candidate);
293
+ else
294
+ advanced.push({ candidate, progress: 1 });
295
+ }
296
+ }
297
+ if (completed.length) {
298
+ clearPending();
299
+ const winner = completed.sort(byPriority)[0];
300
+ if (!winner.binding.allowDefault)
301
+ event.preventDefault();
302
+ winner.source.onMatch({ binding: winner.binding, keys: winner.sequence.source, event });
303
+ return;
304
+ }
305
+ clearPending();
306
+ if (advanced.length) {
307
+ pending = advanced;
308
+ pendingTimer = setTimeout(clearPending, SEQUENCE_TIMEOUT);
309
+ }
310
+ }
311
+ /**
312
+ * Registers `owner`'s bindings with the shared document listener and returns the function that unregisters them.
313
+ * `bindings` is read on every key press, so the owner can change its bindings without registering again. When
314
+ * several bindings match, the one scoped to the element closest to the focused node wins, then the one registered
315
+ * first. The listener calls `preventDefault()` on the key event (unless `allowDefault`) before `onMatch`.
316
+ */
317
+ export function registerShortcuts(owner, bindings, onMatch) {
318
+ const source = { owner, bindings, onMatch: onMatch };
319
+ if (!sources.length && typeof document !== 'undefined')
320
+ document.addEventListener('keydown', handleKeydown);
321
+ sources.push(source);
322
+ return () => {
323
+ const index = sources.indexOf(source);
324
+ if (index < 0)
325
+ return;
326
+ sources.splice(index, 1);
327
+ pending = pending.filter((entry) => entry.candidate.source !== source);
328
+ if (!sources.length) {
329
+ clearPending();
330
+ document.removeEventListener('keydown', handleKeydown);
331
+ }
332
+ };
333
+ }
334
+ //# sourceMappingURL=shortcut-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcut-helper.js","sourceRoot":"","sources":["../src/shortcut-helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAwCH,uDAAuD;AACvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAA;AAEpC,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,GAAG,EAAE,QAAQ;IACb,MAAM,EAAE,OAAO;IACf,KAAK,EAAE,GAAG;IACV,QAAQ,EAAE,GAAG;IACb,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,YAAY;IACnB,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,QAAQ;IACb,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,KAAK,EAAE,GAAG;CACX,CAAA;AAED,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAA;AAEtG,MAAM,UAAU,eAAe;IAC7B,IAAI,OAAO,SAAS,KAAK,WAAW;QAAE,OAAO,KAAK,CAAA;IAClD,MAAM,QAAQ,GAAI,SAAmE,CAAC,aAAa,EAAE,QAAQ,IAAI,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAA;IACzI,OAAO,uBAAuB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,iHAAiH;IACjH,MAAM,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC/G,MAAM,MAAM,GAAmB,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAA;IAC1G,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QACtC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,IAAI,IAAI,KAAK,KAAK;YAAE,MAAM,CAAC,GAAG,GAAG,IAAI,CAAA;aAChC,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;aAC7D,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO;YAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;aACnG,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,KAAK;YAAE,MAAM,CAAC,GAAG,GAAG,IAAI,CAAA;aAC5E,IAAI,IAAI,KAAK,OAAO;YAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAA;;YACzC,MAAM,CAAC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAA;IAC7C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,iHAAiH;AACjH,SAAS,OAAO,CAAC,MAAsB;IACrC,OAAO,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAA;AAC/D,CAAC;AAED,gEAAgE;AAChE,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,GAAG,KAAK,QAAQ,IAAI,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjE,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;AACzE,CAAC;AAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAA;AAEnD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IACzB,MAAM,SAAS,GAAG,IAAI;SACnB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;SACxC,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;SAC5E,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;SACpE,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnB,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC;YAAE,OAAO,IAAI,CAAA;QACzD,OAAO,CAAC,IAAI,CAAC,kBAAkB,QAAQ,CAAC,MAAM,qFAAqF,CAAC,CAAA;QACpI,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAA;IACJ,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC1B,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAsB,EAAE,KAAc;IAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAA;AAC1I,CAAC;AAED,mHAAmH;AACnH,SAAS,OAAO,CAAC,GAAW;IAC1B,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,GAAG,CAAC,WAAW,EAAE,EAAE,CAAA;IACzD,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,GAAG,EAAE,CAAA;IAC7C,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAsB,EAAE,KAAoB,EAAE,KAAK,GAAG,eAAe,EAAE;IACnG,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC/C,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,GAAG;QAAE,OAAO,KAAK,CAAA;IAC/G,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IAC3C,iGAAiG;IACjG,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxD,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAC/E,IAAI,GAAG,KAAK,MAAM,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACnC,6GAA6G;IAC7G,iCAAiC;IACjC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;IACzD,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,gBAAgB,GAA2B;IAC/C,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,GAAG;IACV,SAAS,EAAE,GAAG;IACd,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,GAAG;IACR,GAAG,EAAE,OAAO;IACZ,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,UAAU,EAAE,GAAG;CAChB,CAAA;AAED,MAAM,UAAU,GAA2B;IACzC,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,KAAK;IACb,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,OAAO;IACZ,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,UAAU,EAAE,GAAG;CAChB,CAAA;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,KAAc;IAC3C,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAA;IAC1D,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IACvB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,WAAW,EAAE,CAAA;IAC9C,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACnD,CAAC;AAED,SAAS,WAAW,CAAC,MAAsB,EAAE,KAAc;IACzD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACnE,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACvC,IAAI,KAAK;QAAE,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAA;IAClG,OAAO,CAAC,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI,KAAK,EAAE,GAAG,IAAI,KAAK,EAAE,KAAK,IAAI,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACvG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAK,GAAG,eAAe,EAAE;IACpE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACtH,CAAC;AAED,MAAM,cAAc,GAA2B;IAC7C,GAAG,EAAE,OAAO;IACZ,GAAG,EAAE,MAAM;IACX,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACrB,CAAA;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACnH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAK,GAAG,eAAe,EAAE;IACtE,OAAO,aAAa,CAAC,IAAI,CAAC;SACvB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;SACnD,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE;QAC7B,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACnE,OAAO,CAAC,IAAI,IAAI,SAAS,EAAE,GAAG,IAAI,KAAK,EAAE,KAAK,IAAI,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC/H,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAA;IACtC,IAAI,CAAC,CAAC,MAAM,YAAY,WAAW,CAAC;QAAE,OAAO,KAAK,CAAA;IAClD,IAAI,MAAM,CAAC,iBAAiB,IAAI,MAAM,YAAY,mBAAmB,IAAI,MAAM,YAAY,iBAAiB;QAAE,OAAO,IAAI,CAAA;IACzH,IAAI,CAAC,CAAC,MAAM,YAAY,gBAAgB,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,OAAO,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AACrH,CAAC;AAmBD,MAAM,OAAO,GAAqB,EAAE,CAAA;AACpC,IAAI,OAAO,GAAiD,EAAE,CAAA;AAC9D,IAAI,YAAuD,CAAA;AAE3D,SAAS,YAAY;IACnB,OAAO,GAAG,EAAE,CAAA;IACZ,YAAY,CAAC,YAAY,CAAC,CAAA;IAC1B,YAAY,GAAG,SAAS,CAAA;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,MAAsB,EAAE,KAAyB,EAAE,IAAmB;IACxF,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAA;IACjE,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAA;QACtC,MAAM,YAAY,GAAG,MAAM,YAAY,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAA;QACxE,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5D,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAC/B,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,YAAY,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,6FAA6F;QAC7F,OAAO,CAAC,CAAC,CAAA;IACX,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAoB;IAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAA;IACjC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IACxC,MAAM,UAAU,GAAgB,EAAE,CAAA;IAClC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YACxC,KAAK,IAAI,CAAC,CAAA;YACV,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAQ;YAC9E,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,SAAQ;YAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;YACrD,IAAI,KAAK,GAAG,CAAC;gBAAE,SAAQ;YACvB,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,IAAI,QAAQ,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBAAE,SAAQ;gBACjF,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,CAAY,EAAE,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAA;AAEzF,SAAS,aAAa,CAAC,KAAoB;IACzC,0EAA0E;IAC1E,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAAE,OAAM;IAC9D,+FAA+F;IAC/F,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC3B,YAAY,EAAE,CAAA;QACd,OAAM;IACR,CAAC;IACD,MAAM,KAAK,GAAG,eAAe,EAAE,CAAA;IAC/B,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC5C,MAAM,SAAS,GAAgB,EAAE,CAAA;IACjC,MAAM,QAAQ,GAAiD,EAAE,CAAA;IAEjE,mHAAmH;IACnH,KAAK,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,OAAO,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAA;QAC1G,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;YAAE,SAAQ;QAC1F,IAAI,QAAQ,GAAG,CAAC,KAAK,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;YAAE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;;YACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,CAAC,EAAE,CAAC,CAAA;IAClE,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;gBAAE,SAAQ;YACzE,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;;gBACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;QAChD,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,YAAY,EAAE,CAAA;QACd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY;YAAE,KAAK,CAAC,cAAc,EAAE,CAAA;QACxD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACvF,OAAM;IACR,CAAC;IACD,YAAY,EAAE,CAAA;IACd,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,GAAG,QAAQ,CAAA;QAClB,YAAY,GAAG,UAAU,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAc,EACd,QAA4B,EAC5B,OAA0C;IAE1C,MAAM,MAAM,GAAmB,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAyC,EAAE,CAAA;IACtG,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAC3G,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACpB,OAAO,GAAG,EAAE;QACV,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACrC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAM;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACxB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,CAAA;QACtE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,YAAY,EAAE,CAAA;YACd,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACxD,CAAC;IACH,CAAC,CAAA;AACH,CAAC","sourcesContent":["/**\n * Keyboard shortcuts: parse the `mod+k, mod+k mod+s` syntax, match it against `keydown` events, format it for display\n * and for `aria-keyshortcuts`, and route every registered binding through one shared document listener.\n *\n * Syntax. A binding's `keys` is a comma-separated list of alternatives; an alternative is a space-separated\n * sequence of strokes; a stroke is `+`-joined modifiers followed by one key. `mod` is ⌘ on Apple platforms and\n * Ctrl elsewhere. Key names are `KeyboardEvent.key` values, case-insensitive, plus the aliases in {@link KEY_ALIASES}\n * (`esc`, `space`, `up`, `plus`, `comma`, …) for keys the syntax itself uses.\n *\n * Every stroke must be composed: it holds Ctrl, ⌘ or Alt (Shift alone does not count, `shift+a` is typing). Escape\n * and the function keys F1–F24 are the only keys accepted on their own. An alternative with a bare stroke (`/`,\n * `g d`) is dropped with a console warning.\n *\n * mod+k ⌘K / Ctrl+K\n * mod+k, alt+/ either of two shortcuts\n * mod+k mod+s ⌘K, then ⌘S within a second\n * ctrl+shift+p all three modifiers must match, and no other\n * escape, f1 keys that need no modifier\n */\n\nexport interface ShortcutStroke {\n /** Lowercased `KeyboardEvent.key` (after aliasing). */\n key: string\n ctrl: boolean\n meta: boolean\n alt: boolean\n shift: boolean\n /** `mod` was written: resolves to `meta` on Apple platforms and `ctrl` elsewhere. */\n mod: boolean\n}\n\n/** One alternative of a binding: the strokes pressed in order, and the text it was parsed from. */\nexport interface ShortcutSequence {\n source: string\n strokes: ShortcutStroke[]\n}\n\n/** The options of a binding the shared listener reads. Components extend this with their own fields. */\nexport interface ShortcutBindingOptions {\n keys: string\n /** `global` (default), `parent` (the registering element's parent) or a CSS selector matched against the focus path. */\n scope?: string\n /** Fire even while focus is in an editable field. Strokes with Ctrl, ⌘ or Alt fire there regardless. */\n allowInInputs?: boolean\n /** Leave the browser's own handling of the key alone instead of calling `preventDefault()`. */\n allowDefault?: boolean\n /** Fire again for auto-repeated `keydown` events while the key is held. */\n repeat?: boolean\n disabled?: boolean\n}\n\nexport interface ShortcutMatch<B extends ShortcutBindingOptions = ShortcutBindingOptions> {\n binding: B\n /** The alternative that matched, as written (`alt+/` of `mod+k, alt+/`). */\n keys: string\n event: KeyboardEvent\n}\n\n/** Delay allowed between two strokes of a sequence. */\nexport const SEQUENCE_TIMEOUT = 1000\n\nexport const KEY_ALIASES: Readonly<Record<string, string>> = {\n esc: 'escape',\n return: 'enter',\n space: ' ',\n spacebar: ' ',\n up: 'arrowup',\n down: 'arrowdown',\n left: 'arrowleft',\n right: 'arrowright',\n del: 'delete',\n ins: 'insert',\n plus: '+',\n comma: ',',\n minus: '-',\n}\n\nconst MODIFIER_KEYS = new Set(['control', 'meta', 'alt', 'shift', 'altgraph', 'os', 'capslock', 'fn'])\n\nexport function isApplePlatform(): boolean {\n if (typeof navigator === 'undefined') return false\n const platform = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData?.platform ?? navigator.platform ?? ''\n return /mac|iphone|ipad|ipod/i.test(platform)\n}\n\nfunction parseStroke(raw: string): ShortcutStroke {\n // `+` separates parts, so a trailing `++` is the plus key itself (`ctrl++`); `plus` is the unambiguous spelling.\n const parts = raw === '+' ? ['+'] : raw.endsWith('++') ? [...raw.slice(0, -2).split('+'), '+'] : raw.split('+')\n const stroke: ShortcutStroke = { key: '', ctrl: false, meta: false, alt: false, shift: false, mod: false }\n for (const part of parts) {\n const name = part.trim().toLowerCase()\n if (!name) continue\n if (name === 'mod') stroke.mod = true\n else if (name === 'ctrl' || name === 'control') stroke.ctrl = true\n else if (name === 'meta' || name === 'cmd' || name === 'command' || name === 'super') stroke.meta = true\n else if (name === 'alt' || name === 'option' || name === 'opt') stroke.alt = true\n else if (name === 'shift') stroke.shift = true\n else stroke.key = KEY_ALIASES[name] ?? name\n }\n return stroke\n}\n\n/** Whether the stroke holds Ctrl, ⌘ or Alt, the modifiers that make a key press a command rather than typing. */\nfunction isChord(stroke: ShortcutStroke): boolean {\n return stroke.ctrl || stroke.meta || stroke.alt || stroke.mod\n}\n\n/** Keys that are commands on their own and need no modifier. */\nfunction isStandaloneKey(key: string): boolean {\n return key === 'escape' || /^f([1-9]|1[0-9]|2[0-4])$/.test(key)\n}\n\n/** Whether a stroke is accepted: a chord, or Escape / a function key. */\nexport function isComposedStroke(stroke: ShortcutStroke): boolean {\n return !!stroke.key && (isChord(stroke) || isStandaloneKey(stroke.key))\n}\n\nconst cache = new Map<string, ShortcutSequence[]>()\n\n/**\n * Parses a `keys` string into its alternatives. Malformed alternatives (no key) and alternatives with a stroke that is\n * not composed (see {@link isComposedStroke}) are dropped, the latter with a warning. The comma key has to be written\n * `comma`, since a bare `,` separates alternatives.\n */\nexport function parseShortcut(keys: string): ShortcutSequence[] {\n const cached = cache.get(keys)\n if (cached) return cached\n const sequences = keys\n .split(',')\n .map((alternative) => alternative.trim())\n .filter(Boolean)\n .map((source) => ({ source, strokes: source.split(/\\s+/).map(parseStroke) }))\n .filter((sequence) => sequence.strokes.every((stroke) => stroke.key))\n .filter((sequence) => {\n if (sequence.strokes.every(isComposedStroke)) return true\n console.warn(`[c2-shortcut] \"${sequence.source}\" ignored: every key needs Ctrl, ⌘ or Alt (only Escape and F1–F24 may stand alone).`)\n return false\n })\n cache.set(keys, sequences)\n return sequences\n}\n\nfunction resolvedModifiers(stroke: ShortcutStroke, apple: boolean) {\n return { ctrl: stroke.ctrl || (stroke.mod && !apple), meta: stroke.meta || (stroke.mod && apple), alt: stroke.alt, shift: stroke.shift }\n}\n\n/** The physical key the stroke names, for layouts (and Option on macOS) where `event.key` is another character. */\nfunction codeFor(key: string): string | undefined {\n if (/^[a-z]$/.test(key)) return `Key${key.toUpperCase()}`\n if (/^[0-9]$/.test(key)) return `Digit${key}`\n return undefined\n}\n\nexport function matchesStroke(stroke: ShortcutStroke, event: KeyboardEvent, apple = isApplePlatform()): boolean {\n const wanted = resolvedModifiers(stroke, apple)\n if (event.ctrlKey !== wanted.ctrl || event.metaKey !== wanted.meta || event.altKey !== wanted.alt) return false\n const key = (event.key ?? '').toLowerCase()\n // A symbol such as `?` or `+` already implies whichever Shift state the layout needs to type it.\n const symbol = key.length === 1 && !/[a-z0-9]/.test(key)\n if (!(symbol && !wanted.shift) && event.shiftKey !== wanted.shift) return false\n if (key === stroke.key) return true\n // `event.key` is not plain ASCII (Option+K types `˚`, a Cyrillic layout types `л`, a dead key reads `Dead`):\n // fall back to the physical key.\n const ascii = key.length === 1 && key.charCodeAt(0) < 128\n return !ascii && event.code === codeFor(stroke.key)\n}\n\nconst APPLE_KEY_LABELS: Record<string, string> = {\n escape: 'Esc',\n enter: '↵',\n backspace: '⌫',\n delete: '⌦',\n tab: '⇥',\n ' ': 'Space',\n arrowup: '↑',\n arrowdown: '↓',\n arrowleft: '←',\n arrowright: '→',\n}\n\nconst KEY_LABELS: Record<string, string> = {\n escape: 'Esc',\n enter: 'Enter',\n backspace: 'Backspace',\n delete: 'Del',\n tab: 'Tab',\n ' ': 'Space',\n arrowup: '↑',\n arrowdown: '↓',\n arrowleft: '←',\n arrowright: '→',\n}\n\nfunction keyLabel(key: string, apple: boolean): string {\n const named = (apple ? APPLE_KEY_LABELS : KEY_LABELS)[key]\n if (named) return named\n if (key.length === 1) return key.toUpperCase()\n return key.charAt(0).toUpperCase() + key.slice(1)\n}\n\nfunction strokeLabel(stroke: ShortcutStroke, apple: boolean): string {\n const { ctrl, meta, alt, shift } = resolvedModifiers(stroke, apple)\n const key = keyLabel(stroke.key, apple)\n if (apple) return `${ctrl ? '⌃' : ''}${alt ? '⌥' : ''}${shift ? '⇧' : ''}${meta ? '⌘' : ''}${key}`\n return [ctrl && 'Ctrl', meta && 'Win', alt && 'Alt', shift && 'Shift', key].filter(Boolean).join('+')\n}\n\n/**\n * Human label for each alternative, in the platform's convention: `⌘K` / `⇧⌘P` on Apple platforms, `Ctrl+K` /\n * `Ctrl+Shift+P` elsewhere. Strokes of a sequence are separated by a space (`G D`).\n */\nexport function formatShortcut(keys: string, apple = isApplePlatform()): string[] {\n return parseShortcut(keys).map((sequence) => sequence.strokes.map((stroke) => strokeLabel(stroke, apple)).join(' '))\n}\n\nconst ARIA_KEY_NAMES: Record<string, string> = {\n ' ': 'Space',\n '+': 'Plus',\n arrowup: 'ArrowUp',\n arrowdown: 'ArrowDown',\n arrowleft: 'ArrowLeft',\n arrowright: 'ArrowRight',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n}\n\nfunction ariaKeyName(key: string): string {\n return ARIA_KEY_NAMES[key] ?? (key.length === 1 ? key.toUpperCase() : key.charAt(0).toUpperCase() + key.slice(1))\n}\n\n/**\n * The `aria-keyshortcuts` value for a `keys` string (`Meta+K Control+K` style, one token per alternative). ARIA has\n * no notation for a sequence, so multi-stroke alternatives are left out; an empty string means nothing to announce.\n */\nexport function ariaKeyShortcuts(keys: string, apple = isApplePlatform()): string {\n return parseShortcut(keys)\n .filter((sequence) => sequence.strokes.length === 1)\n .map(({ strokes: [stroke] }) => {\n const { ctrl, meta, alt, shift } = resolvedModifiers(stroke, apple)\n return [ctrl && 'Control', alt && 'Alt', shift && 'Shift', meta && 'Meta', ariaKeyName(stroke.key)].filter(Boolean).join('+')\n })\n .join(' ')\n}\n\n/** Whether a key event comes from a field the user types into (input, textarea, select, contenteditable). */\nexport function isEditableTarget(event: Event): boolean {\n const target = event.composedPath()[0]\n if (!(target instanceof HTMLElement)) return false\n if (target.isContentEditable || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement) return true\n if (!(target instanceof HTMLInputElement)) return false\n return !['button', 'checkbox', 'color', 'file', 'image', 'radio', 'range', 'reset', 'submit'].includes(target.type)\n}\n\n// --- Shared listener ---------------------------------------------------------------------------------------------\n\ninterface ShortcutSource {\n owner: Element\n bindings: () => readonly ShortcutBindingOptions[]\n onMatch: (match: ShortcutMatch) => void\n}\n\ninterface Candidate {\n source: ShortcutSource\n binding: ShortcutBindingOptions\n sequence: ShortcutSequence\n /** Position in the focus path of the element that scopes the binding (`Infinity` for global). Lower wins. */\n depth: number\n order: number\n}\n\nconst sources: ShortcutSource[] = []\nlet pending: { candidate: Candidate; progress: number }[] = []\nlet pendingTimer: ReturnType<typeof setTimeout> | undefined\n\nfunction clearPending() {\n pending = []\n clearTimeout(pendingTimer)\n pendingTimer = undefined\n}\n\nfunction scopeDepth(source: ShortcutSource, scope: string | undefined, path: EventTarget[]): number {\n if (!scope || scope === 'global') return Number.POSITIVE_INFINITY\n if (scope === 'parent') {\n const parent = source.owner.parentNode\n const scopeElement = parent instanceof ShadowRoot ? parent.host : parent\n const index = scopeElement ? path.indexOf(scopeElement) : -1\n return index < 0 ? -1 : index\n }\n try {\n return path.findIndex((node) => node instanceof Element && node.matches(scope))\n } catch {\n // An invalid selector scopes the binding to nothing rather than throwing on every key press.\n return -1\n }\n}\n\nfunction eligibleCandidates(event: KeyboardEvent): Candidate[] {\n const path = event.composedPath()\n const editable = isEditableTarget(event)\n const candidates: Candidate[] = []\n let order = 0\n for (const source of sources) {\n for (const binding of source.bindings()) {\n order += 1\n if (!binding || binding.disabled || typeof binding.keys !== 'string') continue\n if (event.repeat && !binding.repeat) continue\n const depth = scopeDepth(source, binding.scope, path)\n if (depth < 0) continue\n for (const sequence of parseShortcut(binding.keys)) {\n if (editable && !binding.allowInInputs && !isChord(sequence.strokes[0])) continue\n candidates.push({ source, binding, sequence, depth, order })\n }\n }\n }\n return candidates\n}\n\nconst byPriority = (a: Candidate, b: Candidate) => a.depth - b.depth || a.order - b.order\n\nfunction handleKeydown(event: KeyboardEvent) {\n // A pressed modifier on its own is part of the next stroke, not a stroke.\n if (MODIFIER_KEYS.has((event.key ?? '').toLowerCase())) return\n // A component that already handled the key (a list's arrow keys, a menu's typeahead) keeps it.\n if (event.defaultPrevented) {\n clearPending()\n return\n }\n const apple = isApplePlatform()\n const candidates = eligibleCandidates(event)\n const completed: Candidate[] = []\n const advanced: { candidate: Candidate; progress: number }[] = []\n\n // Sequences already under way come first: after ⌘K, ⌘S completes `mod+k mod+s` rather than a lone `mod+s` binding.\n for (const { candidate, progress } of pending) {\n const still = candidates.find((c) => c.binding === candidate.binding && c.sequence === candidate.sequence)\n if (!still || !matchesStroke(candidate.sequence.strokes[progress], event, apple)) continue\n if (progress + 1 === candidate.sequence.strokes.length) completed.push(still)\n else advanced.push({ candidate: still, progress: progress + 1 })\n }\n if (!completed.length) {\n for (const candidate of candidates) {\n if (!matchesStroke(candidate.sequence.strokes[0], event, apple)) continue\n if (candidate.sequence.strokes.length === 1) completed.push(candidate)\n else advanced.push({ candidate, progress: 1 })\n }\n }\n\n if (completed.length) {\n clearPending()\n const winner = completed.sort(byPriority)[0]\n if (!winner.binding.allowDefault) event.preventDefault()\n winner.source.onMatch({ binding: winner.binding, keys: winner.sequence.source, event })\n return\n }\n clearPending()\n if (advanced.length) {\n pending = advanced\n pendingTimer = setTimeout(clearPending, SEQUENCE_TIMEOUT)\n }\n}\n\n/**\n * Registers `owner`'s bindings with the shared document listener and returns the function that unregisters them.\n * `bindings` is read on every key press, so the owner can change its bindings without registering again. When\n * several bindings match, the one scoped to the element closest to the focused node wins, then the one registered\n * first. The listener calls `preventDefault()` on the key event (unless `allowDefault`) before `onMatch`.\n */\nexport function registerShortcuts<B extends ShortcutBindingOptions>(\n owner: Element,\n bindings: () => readonly B[],\n onMatch: (match: ShortcutMatch<B>) => void,\n): () => void {\n const source: ShortcutSource = { owner, bindings, onMatch: onMatch as (match: ShortcutMatch) => void }\n if (!sources.length && typeof document !== 'undefined') document.addEventListener('keydown', handleKeydown)\n sources.push(source)\n return () => {\n const index = sources.indexOf(source)\n if (index < 0) return\n sources.splice(index, 1)\n pending = pending.filter((entry) => entry.candidate.source !== source)\n if (!sources.length) {\n clearPending()\n document.removeEventListener('keydown', handleKeydown)\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c2n/core",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "scripts": {
5
5
  "dev": "tsc -p tsconfig.json -w",
6
6
  "build": "tsc -p tsconfig.json"
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/lit-helper.d.ts",
33
33
  "default": "./dist/lit-helper.js"
34
34
  },
35
+ "./shortcut-helper.js": {
36
+ "types": "./dist/shortcut-helper.d.ts",
37
+ "default": "./dist/shortcut-helper.js"
38
+ },
35
39
  "./contexts/pager.js": {
36
40
  "types": "./dist/contexts/pager.d.ts",
37
41
  "default": "./dist/contexts/pager.js"
@@ -68,5 +72,5 @@
68
72
  "devDependencies": {
69
73
  "@c2n/config": "*"
70
74
  },
71
- "gitHead": "0f012d5c8f91bb1bf7c1a39437147f76802c6a6f"
75
+ "gitHead": "97db30ae10cfe0b1571ba5081116bc134422fce4"
72
76
  }