@threadlabs/looma 0.37.4 → 0.37.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/components/shared/active-item-reveal.js +74 -0
  2. package/components/shared/menu-navigation.js +3 -1
  3. package/components/ui-button/ui-button.html +13 -0
  4. package/components/ui-combobox/ui-combobox.js +3 -1
  5. package/components/ui-context-menu/ui-context-menu.js +4 -1
  6. package/components/ui-editor-link-form/ui-editor-link-form.js +3 -1
  7. package/components/ui-editor-mention-menu/ui-editor-mention-menu.js +12 -5
  8. package/components/ui-editor-slash-menu/ui-editor-slash-menu.js +12 -5
  9. package/components/ui-listbox/ui-listbox.js +3 -1
  10. package/components/ui-menu/ui-menu.js +5 -1
  11. package/components/ui-pagination/ui-pagination.html +74 -0
  12. package/components/ui-pagination/ui-pagination.js +19 -0
  13. package/components/ui-search-shell/ui-search-shell.js +7 -4
  14. package/components/ui-skeleton/ui-skeleton.html +91 -0
  15. package/dist/index.js +20 -19
  16. package/docs/catalog.json +491 -1
  17. package/docs/examples/ui-pagination/examples/01-numbered.behavior.js +11 -0
  18. package/package.json +1 -1
  19. package/styles/ui-button.css +12 -0
  20. package/styles/ui-pagination.css +1 -0
  21. package/styles/ui-skeleton.css +91 -0
  22. package/vanilla/UiButton.d.ts +1 -0
  23. package/vanilla/UiButton.js +31 -31
  24. package/vanilla/UiPagination.d.ts +35 -0
  25. package/vanilla/UiPagination.js +202 -0
  26. package/vanilla/UiSkeleton.d.ts +26 -0
  27. package/vanilla/UiSkeleton.js +42 -0
  28. package/vanilla/index.js +2 -0
  29. package/vue/UiButton.d.ts +6 -0
  30. package/vue/UiButton.vue +34 -0
  31. package/vue/UiPagination.d.ts +115 -0
  32. package/vue/UiPagination.js +2 -0
  33. package/vue/UiPagination.vue +598 -0
  34. package/vue/UiSkeleton.d.ts +37 -0
  35. package/vue/UiSkeleton.js +2 -0
  36. package/vue/UiSkeleton.vue +235 -0
  37. package/vue/chunks/UiActionBar.js +1 -1
  38. package/vue/chunks/UiAffordanceScope.js +1 -1
  39. package/vue/chunks/UiAvatar.js +1 -1
  40. package/vue/chunks/UiAvatarGroup.js +1 -1
  41. package/vue/chunks/UiBadge.js +1 -1
  42. package/vue/chunks/UiBreadcrumbItem.js +1 -1
  43. package/vue/chunks/UiBreadcrumbs.js +1 -1
  44. package/vue/chunks/UiButton.js +30 -2
  45. package/vue/chunks/UiCallout.js +1 -1
  46. package/vue/chunks/UiCard.js +1 -1
  47. package/vue/chunks/UiCheckbox.js +1 -1
  48. package/vue/chunks/UiCluster.js +1 -1
  49. package/vue/chunks/UiColorPicker.js +1 -1
  50. package/vue/chunks/UiCombobox.js +1 -1
  51. package/vue/chunks/UiContainer.js +1 -1
  52. package/vue/chunks/UiContextMenu.js +1 -1
  53. package/vue/chunks/UiCover.js +1 -1
  54. package/vue/chunks/UiCurveEditor.js +1 -1
  55. package/vue/chunks/UiCycleButton.js +1 -1
  56. package/vue/chunks/UiDescriptionItem.js +1 -1
  57. package/vue/chunks/UiDescriptionList.js +1 -1
  58. package/vue/chunks/UiDialog.js +1 -1
  59. package/vue/chunks/UiDisclosure.js +1 -1
  60. package/vue/chunks/UiEditable.js +1 -1
  61. package/vue/chunks/UiEditorBlockActions.js +1 -1
  62. package/vue/chunks/UiEditorChipEditor.js +1 -1
  63. package/vue/chunks/UiEditorCodeLanguage.js +1 -1
  64. package/vue/chunks/UiEditorFootnoteEditor.js +1 -1
  65. package/vue/chunks/UiEditorImageToolbar.js +1 -1
  66. package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
  67. package/vue/chunks/UiEditorLinkCard.js +1 -1
  68. package/vue/chunks/UiEditorLinkForm.js +1 -1
  69. package/vue/chunks/UiEditorMentionMenu.js +1 -1
  70. package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
  71. package/vue/chunks/UiEditorSlashMenu.js +1 -1
  72. package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
  73. package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
  74. package/vue/chunks/UiEditorSurface.js +1 -1
  75. package/vue/chunks/UiEditorTableContextMenu.js +1 -1
  76. package/vue/chunks/UiEditorTableOverlay.js +1 -1
  77. package/vue/chunks/UiEditorTableToolbar.js +1 -1
  78. package/vue/chunks/UiEditorToolbar.js +1 -1
  79. package/vue/chunks/UiFloatingActionButton.js +1 -1
  80. package/vue/chunks/UiFormField.js +1 -1
  81. package/vue/chunks/UiGrid.js +1 -1
  82. package/vue/chunks/UiIcon.js +1 -1
  83. package/vue/chunks/UiIconButton.js +1 -1
  84. package/vue/chunks/UiImage.js +1 -1
  85. package/vue/chunks/UiInput.js +1 -1
  86. package/vue/chunks/UiInputGroup.js +1 -1
  87. package/vue/chunks/UiLightEditor.js +1 -1
  88. package/vue/chunks/UiList.js +1 -1
  89. package/vue/chunks/UiListItem.js +1 -1
  90. package/vue/chunks/UiListbox.js +1 -1
  91. package/vue/chunks/UiMenu.js +1 -1
  92. package/vue/chunks/UiMenuGroup.js +1 -1
  93. package/vue/chunks/UiMenuItem.js +1 -1
  94. package/vue/chunks/UiMeter.js +1 -1
  95. package/vue/chunks/UiNavItem.js +1 -1
  96. package/vue/chunks/UiNumberInput.js +1 -1
  97. package/vue/chunks/UiPageHeader.js +1 -1
  98. package/vue/chunks/UiPagination.js +551 -0
  99. package/vue/chunks/UiPopover.js +1 -1
  100. package/vue/chunks/UiRadio.js +1 -1
  101. package/vue/chunks/UiRadioGroup.js +1 -1
  102. package/vue/chunks/UiReel.js +1 -1
  103. package/vue/chunks/UiScrollArea.js +1 -1
  104. package/vue/chunks/UiSearchResultRow.js +1 -1
  105. package/vue/chunks/UiSearchShell.js +1 -1
  106. package/vue/chunks/UiSection.js +1 -1
  107. package/vue/chunks/UiSelect.js +1 -1
  108. package/vue/chunks/UiSeparator.js +1 -1
  109. package/vue/chunks/UiSidebar.js +1 -1
  110. package/vue/chunks/UiSkeleton.js +151 -0
  111. package/vue/chunks/UiSlider.js +1 -1
  112. package/vue/chunks/UiSpinner.js +1 -1
  113. package/vue/chunks/UiStack.js +1 -1
  114. package/vue/chunks/UiStatusMessage.js +1 -1
  115. package/vue/chunks/UiSwatch.js +1 -1
  116. package/vue/chunks/UiSwitch.js +1 -1
  117. package/vue/chunks/UiSwitcher.js +1 -1
  118. package/vue/chunks/UiTable.js +1 -1
  119. package/vue/chunks/UiTabs.js +1 -1
  120. package/vue/chunks/UiText.js +1 -1
  121. package/vue/chunks/UiTextarea.js +1 -1
  122. package/vue/chunks/UiToast.js +1 -1
  123. package/vue/chunks/UiToastRegion.js +1 -1
  124. package/vue/chunks/UiTooltip.js +1 -1
  125. package/vue/chunks/UiTopBar.js +1 -1
  126. package/vue/chunks/UiTree.js +1 -1
  127. package/vue/chunks/UiTreeItem.js +1 -1
  128. package/vue/chunks/_plugin-vue_export-helper.js +27 -2
  129. package/vue/components.css +93 -0
  130. package/vue/editor/index.js +139 -35
  131. package/vue/index.d.ts +2 -0
  132. package/vue/index.js +3 -1
package/docs/catalog.json CHANGED
@@ -305,6 +305,11 @@
305
305
  "package": "@threadlabs/looma",
306
306
  "resource": "@threadlabs/looma/components/ui-page-header/ui-page-header.html"
307
307
  },
308
+ {
309
+ "tag": "ui-pagination",
310
+ "package": "@threadlabs/looma",
311
+ "resource": "@threadlabs/looma/components/ui-pagination/ui-pagination.html"
312
+ },
308
313
  {
309
314
  "tag": "ui-popover",
310
315
  "package": "@threadlabs/looma",
@@ -360,6 +365,11 @@
360
365
  "package": "@threadlabs/looma",
361
366
  "resource": "@threadlabs/looma/components/ui-sidebar/ui-sidebar.html"
362
367
  },
368
+ {
369
+ "tag": "ui-skeleton",
370
+ "package": "@threadlabs/looma",
371
+ "resource": "@threadlabs/looma/components/ui-skeleton/ui-skeleton.html"
372
+ },
363
373
  {
364
374
  "tag": "ui-slider",
365
375
  "package": "@threadlabs/looma",
@@ -448,7 +458,7 @@
448
458
  ],
449
459
  "schemaVersion": 1,
450
460
  "package": "@threadlabs/looma",
451
- "version": "0.37.4",
461
+ "version": "0.37.6",
452
462
  "groups": [
453
463
  {
454
464
  "id": "layout",
@@ -2544,6 +2554,13 @@
2544
2554
  "lg"
2545
2555
  ]
2546
2556
  },
2557
+ {
2558
+ "name": "square",
2559
+ "property": "square",
2560
+ "description": "Gives short labels and icons the same square minimum footprint at each size. Longer labels grow naturally. Applies to boxed actions; link and card variants keep their normal layout.",
2561
+ "type": "boolean",
2562
+ "default": false
2563
+ },
2547
2564
  {
2548
2565
  "name": "stretch",
2549
2566
  "property": "stretch",
@@ -2685,6 +2702,12 @@
2685
2702
  "lg"
2686
2703
  ]
2687
2704
  },
2705
+ {
2706
+ "name": "square",
2707
+ "description": "Gives short labels and icons the same square minimum footprint at each size. Longer labels grow naturally. Applies to boxed actions; link and card variants keep their normal layout.",
2708
+ "type": "boolean",
2709
+ "default": false
2710
+ },
2688
2711
  {
2689
2712
  "name": "stretch",
2690
2713
  "description": "Fills the inline size of its container.",
@@ -2865,6 +2888,16 @@
2865
2888
  "bindings": "",
2866
2889
  "frameworks": {}
2867
2890
  },
2891
+ {
2892
+ "id": "@threadlabs/looma/ui-button/09-square",
2893
+ "name": "09-square",
2894
+ "title": "Square minimum size",
2895
+ "description": "Short numeric and icon actions share the control's minimum height and width. Longer labels grow naturally; the ordinary Button default stays content-sized.",
2896
+ "markup": "<ui-cluster gap=\"xs\"><ui-button square size=\"sm\" variant=\"ghost\" tone=\"neutral\" aria-label=\"Previous\"><ui-icon\n name=\"chevron-left\"\n ></ui-icon></ui-button><ui-button square size=\"sm\" variant=\"ghost\" tone=\"neutral\">1</ui-button><ui-button square size=\"sm\" variant=\"solid\"\n >2</ui-button><ui-button square size=\"sm\" variant=\"ghost\" tone=\"neutral\">10</ui-button><ui-button\n square\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label=\"Next\"\n ><ui-icon name=\"chevron-right\"></ui-icon></ui-button></ui-cluster>",
2897
+ "resizable": false,
2898
+ "bindings": "",
2899
+ "frameworks": {}
2900
+ },
2868
2901
  {
2869
2902
  "id": "@threadlabs/looma/ui-button/10-card",
2870
2903
  "name": "10-card",
@@ -17186,6 +17219,300 @@
17186
17219
  }
17187
17220
  ]
17188
17221
  },
17222
+ {
17223
+ "tag": "ui-pagination",
17224
+ "package": "@threadlabs/looma",
17225
+ "root": "nav",
17226
+ "description": "Controlled page navigation for result lists, cards and tables. Supply the visible numbered pages and previous/next availability; Looma owns the native controls, current-page semantics and navigate requests. Optional hrefs preserve ordinary link navigation. Applications own routes, data fetching and page windows.",
17227
+ "designTokens": {
17228
+ "sources": [
17229
+ "packages/looma/src/components/ui-pagination/ui-pagination.html"
17230
+ ],
17231
+ "component": [],
17232
+ "shared": []
17233
+ },
17234
+ "attributes": [
17235
+ {
17236
+ "name": "disabled",
17237
+ "property": "disabled",
17238
+ "description": "Makes all page controls unavailable while keeping the current page visible.",
17239
+ "type": "boolean",
17240
+ "default": false
17241
+ },
17242
+ {
17243
+ "name": "has-next",
17244
+ "property": "hasNext",
17245
+ "description": "Whether another page is available. The component does not infer a total.",
17246
+ "type": "boolean",
17247
+ "default": false
17248
+ },
17249
+ {
17250
+ "name": "has-previous",
17251
+ "property": "hasPrevious",
17252
+ "description": "Whether a preceding page is available. Previous is always unavailable on page one.",
17253
+ "type": "boolean",
17254
+ "default": false
17255
+ },
17256
+ {
17257
+ "name": "label",
17258
+ "property": "label",
17259
+ "description": "Accessible name for the navigation landmark.",
17260
+ "type": "string",
17261
+ "default": "Results pages"
17262
+ },
17263
+ {
17264
+ "name": "next-href",
17265
+ "property": "nextHref",
17266
+ "description": "Optional native destination for Next. Empty renders a request button.",
17267
+ "type": "string",
17268
+ "default": ""
17269
+ },
17270
+ {
17271
+ "name": "next-label",
17272
+ "property": "nextLabel",
17273
+ "description": "Accessible label for the following page action.",
17274
+ "type": "string",
17275
+ "default": "Next"
17276
+ },
17277
+ {
17278
+ "name": "page",
17279
+ "property": "page",
17280
+ "description": "Current one-based page. The consumer updates it after a navigate request; activation never changes it internally.",
17281
+ "type": "number",
17282
+ "default": 1
17283
+ },
17284
+ {
17285
+ "name": "page-label",
17286
+ "property": "pageLabel",
17287
+ "description": "Prefix for each numbered page's accessible name, followed by its localized number.",
17288
+ "type": "string",
17289
+ "default": "Page"
17290
+ },
17291
+ {
17292
+ "name": "pages",
17293
+ "property": "pages",
17294
+ "description": "Visible numbered pages in ascending order. Omit for previous/next navigation without a known total. Gaps between numbers show an ellipsis. Supply href to keep a numbered page usable as a native link before JavaScript.",
17295
+ "type": "list(object)",
17296
+ "fields": [
17297
+ {
17298
+ "path": "[].value",
17299
+ "type": "number",
17300
+ "required": true
17301
+ },
17302
+ {
17303
+ "path": "[].href",
17304
+ "type": "string",
17305
+ "required": false
17306
+ }
17307
+ ],
17308
+ "default": "[]"
17309
+ },
17310
+ {
17311
+ "name": "previous-href",
17312
+ "property": "previousHref",
17313
+ "description": "Optional native destination for Previous. Empty renders a request button.",
17314
+ "type": "string",
17315
+ "default": ""
17316
+ },
17317
+ {
17318
+ "name": "previous-label",
17319
+ "property": "previousLabel",
17320
+ "description": "Accessible label for the preceding page action.",
17321
+ "type": "string",
17322
+ "default": "Previous"
17323
+ },
17324
+ {
17325
+ "name": "size",
17326
+ "property": "size",
17327
+ "description": "Uses Button's shared size scale. Narrow groups wrap without enlarging compact controls.",
17328
+ "type": "keyword",
17329
+ "default": "sm",
17330
+ "options": [
17331
+ "sm",
17332
+ "md",
17333
+ "lg"
17334
+ ]
17335
+ }
17336
+ ],
17337
+ "properties": [
17338
+ {
17339
+ "name": "disabled",
17340
+ "description": "Makes all page controls unavailable while keeping the current page visible.",
17341
+ "type": "boolean",
17342
+ "default": false
17343
+ },
17344
+ {
17345
+ "name": "hasNext",
17346
+ "description": "Whether another page is available. The component does not infer a total.",
17347
+ "type": "boolean",
17348
+ "default": false
17349
+ },
17350
+ {
17351
+ "name": "hasPrevious",
17352
+ "description": "Whether a preceding page is available. Previous is always unavailable on page one.",
17353
+ "type": "boolean",
17354
+ "default": false
17355
+ },
17356
+ {
17357
+ "name": "label",
17358
+ "description": "Accessible name for the navigation landmark.",
17359
+ "type": "string",
17360
+ "default": "Results pages"
17361
+ },
17362
+ {
17363
+ "name": "nextHref",
17364
+ "description": "Optional native destination for Next. Empty renders a request button.",
17365
+ "type": "string",
17366
+ "default": ""
17367
+ },
17368
+ {
17369
+ "name": "nextLabel",
17370
+ "description": "Accessible label for the following page action.",
17371
+ "type": "string",
17372
+ "default": "Next"
17373
+ },
17374
+ {
17375
+ "name": "page",
17376
+ "description": "Current one-based page. The consumer updates it after a navigate request; activation never changes it internally.",
17377
+ "type": "number",
17378
+ "default": 1
17379
+ },
17380
+ {
17381
+ "name": "pageLabel",
17382
+ "description": "Prefix for each numbered page's accessible name, followed by its localized number.",
17383
+ "type": "string",
17384
+ "default": "Page"
17385
+ },
17386
+ {
17387
+ "name": "pages",
17388
+ "description": "Visible numbered pages in ascending order. Omit for previous/next navigation without a known total. Gaps between numbers show an ellipsis. Supply href to keep a numbered page usable as a native link before JavaScript.",
17389
+ "type": "readonly ({ readonly value: number; readonly href?: string | null })[]",
17390
+ "fields": [
17391
+ {
17392
+ "path": "[].value",
17393
+ "type": "number",
17394
+ "required": true
17395
+ },
17396
+ {
17397
+ "path": "[].href",
17398
+ "type": "string",
17399
+ "required": false
17400
+ }
17401
+ ],
17402
+ "default": "[]"
17403
+ },
17404
+ {
17405
+ "name": "previousHref",
17406
+ "description": "Optional native destination for Previous. Empty renders a request button.",
17407
+ "type": "string",
17408
+ "default": ""
17409
+ },
17410
+ {
17411
+ "name": "previousLabel",
17412
+ "description": "Accessible label for the preceding page action.",
17413
+ "type": "string",
17414
+ "default": "Previous"
17415
+ },
17416
+ {
17417
+ "name": "size",
17418
+ "description": "Uses Button's shared size scale. Narrow groups wrap without enlarging compact controls.",
17419
+ "type": "\"sm\" | \"md\" | \"lg\"",
17420
+ "default": "sm",
17421
+ "options": [
17422
+ "sm",
17423
+ "md",
17424
+ "lg"
17425
+ ]
17426
+ }
17427
+ ],
17428
+ "events": [
17429
+ {
17430
+ "name": "navigate",
17431
+ "detailType": "{ readonly page: number; readonly previousPage: number; readonly trigger: \"keyboard\" | \"pointer\" | \"programmatic\" }",
17432
+ "detailSchema": "object",
17433
+ "fields": [
17434
+ {
17435
+ "path": "page",
17436
+ "type": "number",
17437
+ "required": true
17438
+ },
17439
+ {
17440
+ "path": "previousPage",
17441
+ "type": "number",
17442
+ "required": true
17443
+ },
17444
+ {
17445
+ "path": "trigger",
17446
+ "type": "keyword",
17447
+ "required": true,
17448
+ "values": [
17449
+ "keyboard",
17450
+ "pointer",
17451
+ "programmatic"
17452
+ ]
17453
+ }
17454
+ ],
17455
+ "detailDocs": "Emitted with the declared detail payload."
17456
+ }
17457
+ ],
17458
+ "slots": [
17459
+ {
17460
+ "name": "default",
17461
+ "description": "Default child content."
17462
+ }
17463
+ ],
17464
+ "group": "display",
17465
+ "id": "@threadlabs/looma/ui-pagination",
17466
+ "title": "Pagination",
17467
+ "resource": "@threadlabs/looma/components/ui-pagination/ui-pagination.html",
17468
+ "targets": [
17469
+ "html-next",
17470
+ "vue"
17471
+ ],
17472
+ "examples": [
17473
+ {
17474
+ "id": "@threadlabs/looma/ui-pagination/01-numbered",
17475
+ "name": "01-numbered",
17476
+ "title": "Numbered pages",
17477
+ "description": "The consumer supplies a bounded page window. Omitted page numbers produce a quiet ellipsis; the current page remains consumer controlled.",
17478
+ "markup": "<ui-pagination page=\"3\" has-previous has-next pages='[{\"value\":1},{\"value\":2},{\"value\":3},{\"value\":4},{\"value\":10}]'></ui-pagination>",
17479
+ "resizable": false,
17480
+ "bindings": "",
17481
+ "frameworks": {},
17482
+ "behavior": "@threadlabs/looma/docs/examples/ui-pagination/examples/01-numbered.behavior.js"
17483
+ },
17484
+ {
17485
+ "id": "@threadlabs/looma/ui-pagination/02-native-links",
17486
+ "name": "02-native-links",
17487
+ "title": "Native links",
17488
+ "description": "Supplied hrefs stay ordinary links before upgrade and retain modified-click and open-in-new-tab behavior. Replace these example query destinations with your own routes.",
17489
+ "markup": "<ui-pagination\n page=\"2\"\n label=\"Catalog pages\"\n has-previous\n has-next\n previous-href=\"?page=1\"\n next-href=\"?page=3\"\n pages='[{\"value\":1,\"href\":\"?page=1\"},{\"value\":2,\"href\":\"?page=2\"},{\"value\":3,\"href\":\"?page=3\"}]'\n></ui-pagination>",
17490
+ "resizable": false,
17491
+ "bindings": "",
17492
+ "frameworks": {}
17493
+ },
17494
+ {
17495
+ "id": "@threadlabs/looma/ui-pagination/03-unknown-total",
17496
+ "name": "03-unknown-total",
17497
+ "title": "Unknown total",
17498
+ "description": "Previous and Next work without an invented page count. The application decides availability from its result or cursor data.",
17499
+ "markup": "<ui-pagination page=\"3\" has-previous has-next><ui-text size=\"sm\" tone=\"secondary\">Page 3</ui-text></ui-pagination>",
17500
+ "resizable": false,
17501
+ "bindings": "",
17502
+ "frameworks": {}
17503
+ },
17504
+ {
17505
+ "id": "@threadlabs/looma/ui-pagination/04-table",
17506
+ "name": "04-table",
17507
+ "title": "Beside a results table",
17508
+ "description": "Table owns its rows, Pagination owns page controls, and Stack owns their spacing. Data retrieval and sorting stay with the application.",
17509
+ "markup": "<ui-stack gap=\"m\">\n <ui-table density=\"compact\"><table>\n <caption>Catalog results</caption>\n <thead>\n <tr>\n <th scope=\"col\">Item</th>\n <th scope=\"col\">Status</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th scope=\"row\">Field guide</th>\n <td>Available</td>\n </tr>\n <tr>\n <th scope=\"row\">Trail notes</th>\n <td>Available</td>\n </tr>\n </tbody>\n </table></ui-table>\n <ui-pagination page=\"1\" has-next pages='[{\"value\":1},{\"value\":2},{\"value\":3}]'></ui-pagination>\n</ui-stack>",
17510
+ "resizable": false,
17511
+ "bindings": "",
17512
+ "frameworks": {}
17513
+ }
17514
+ ]
17515
+ },
17189
17516
  {
17190
17517
  "tag": "ui-popover",
17191
17518
  "package": "@threadlabs/looma",
@@ -20077,6 +20404,169 @@
20077
20404
  }
20078
20405
  ]
20079
20406
  },
20407
+ {
20408
+ "tag": "ui-skeleton",
20409
+ "package": "@threadlabs/looma",
20410
+ "root": "span",
20411
+ "description": "Reserve the shape of incoming content without announcing each placeholder. Text follows the surrounding line metrics; circles and rectangles stand in for avatars and media. Use one status message and aria-busy on the loading region, then replace the placeholders with real content. Keep existing content visible during refresh when possible. Animation is optional and respects reduced motion.",
20412
+ "designTokens": {
20413
+ "sources": [
20414
+ "packages/looma/src/components/ui-skeleton/ui-skeleton.html"
20415
+ ],
20416
+ "component": [
20417
+ {
20418
+ "name": "--ui-skeleton-height",
20419
+ "fallbacks": [
20420
+ "1lh",
20421
+ "auto",
20422
+ "8rem"
20423
+ ]
20424
+ },
20425
+ {
20426
+ "name": "--ui-skeleton-width",
20427
+ "fallbacks": [
20428
+ "100%",
20429
+ "calc(2.5rem + 2 * var(--ui-border-width))"
20430
+ ]
20431
+ }
20432
+ ],
20433
+ "shared": [
20434
+ {
20435
+ "name": "--ui-border-width"
20436
+ },
20437
+ {
20438
+ "name": "--ui-radius-md"
20439
+ },
20440
+ {
20441
+ "name": "--ui-radius-round"
20442
+ },
20443
+ {
20444
+ "name": "--ui-radius-sm"
20445
+ },
20446
+ {
20447
+ "name": "--ui-text-primary"
20448
+ }
20449
+ ]
20450
+ },
20451
+ "attributes": [
20452
+ {
20453
+ "name": "animated",
20454
+ "property": "animated",
20455
+ "description": "Gently pulses the placeholder. Off by default, and always still when the reader requests reduced motion.",
20456
+ "type": "boolean",
20457
+ "default": false
20458
+ },
20459
+ {
20460
+ "name": "height",
20461
+ "property": "height",
20462
+ "description": "Block size as a CSS length. Empty reserves one line for text, a square for circles, or 8rem for rectangles. Set only width to keep a circle square.",
20463
+ "type": "string",
20464
+ "default": ""
20465
+ },
20466
+ {
20467
+ "name": "shape",
20468
+ "property": "shape",
20469
+ "description": "The content's silhouette. text reserves one inherited line box with a shorter bar inside it; circle matches a medium Avatar; rectangle reserves a media area.",
20470
+ "type": "keyword",
20471
+ "default": "text",
20472
+ "options": [
20473
+ "text",
20474
+ "circle",
20475
+ "rectangle"
20476
+ ]
20477
+ },
20478
+ {
20479
+ "name": "width",
20480
+ "property": "width",
20481
+ "description": "Inline size as a CSS length or percentage, constrained to the container. Empty fills the available width for text and rectangles, or matches a medium Avatar's outer size for circles.",
20482
+ "type": "string",
20483
+ "default": ""
20484
+ }
20485
+ ],
20486
+ "properties": [
20487
+ {
20488
+ "name": "animated",
20489
+ "description": "Gently pulses the placeholder. Off by default, and always still when the reader requests reduced motion.",
20490
+ "type": "boolean",
20491
+ "default": false
20492
+ },
20493
+ {
20494
+ "name": "height",
20495
+ "description": "Block size as a CSS length. Empty reserves one line for text, a square for circles, or 8rem for rectangles. Set only width to keep a circle square.",
20496
+ "type": "string",
20497
+ "default": ""
20498
+ },
20499
+ {
20500
+ "name": "shape",
20501
+ "description": "The content's silhouette. text reserves one inherited line box with a shorter bar inside it; circle matches a medium Avatar; rectangle reserves a media area.",
20502
+ "type": "\"text\" | \"circle\" | \"rectangle\"",
20503
+ "default": "text",
20504
+ "options": [
20505
+ "text",
20506
+ "circle",
20507
+ "rectangle"
20508
+ ]
20509
+ },
20510
+ {
20511
+ "name": "width",
20512
+ "description": "Inline size as a CSS length or percentage, constrained to the container. Empty fills the available width for text and rectangles, or matches a medium Avatar's outer size for circles.",
20513
+ "type": "string",
20514
+ "default": ""
20515
+ }
20516
+ ],
20517
+ "events": [],
20518
+ "slots": [],
20519
+ "group": "display",
20520
+ "id": "@threadlabs/looma/ui-skeleton",
20521
+ "title": "Skeleton",
20522
+ "resource": "@threadlabs/looma/components/ui-skeleton/ui-skeleton.html",
20523
+ "targets": [
20524
+ "html-next",
20525
+ "vue"
20526
+ ],
20527
+ "examples": [
20528
+ {
20529
+ "id": "@threadlabs/looma/ui-skeleton/01-text",
20530
+ "name": "01-text",
20531
+ "title": "Text lines",
20532
+ "description": "Each placeholder reserves a whole text line. Vary the widths to suggest the content without pretending to know its words.",
20533
+ "markup": "<ui-stack gap=\"none\">\n <ui-skeleton></ui-skeleton>\n <ui-skeleton width=\"85%\"></ui-skeleton>\n <ui-skeleton width=\"60%\"></ui-skeleton>\n</ui-stack>",
20534
+ "resizable": false,
20535
+ "bindings": "",
20536
+ "frameworks": {}
20537
+ },
20538
+ {
20539
+ "id": "@threadlabs/looma/ui-skeleton/02-shapes",
20540
+ "name": "02-shapes",
20541
+ "title": "Avatar and media shapes",
20542
+ "description": "The default circle matches a medium Avatar. Supply dimensions for a thumbnail or a larger media area; narrow containers constrain the width.",
20543
+ "markup": "<ui-stack gap=\"m\">\n <ui-cluster gap=\"m\">\n <ui-skeleton shape=\"circle\"></ui-skeleton>\n <ui-skeleton shape=\"circle\" width=\"1.75rem\"></ui-skeleton>\n <ui-skeleton shape=\"rectangle\" width=\"6rem\" height=\"2.5rem\"></ui-skeleton>\n </ui-cluster>\n <ui-skeleton shape=\"rectangle\"></ui-skeleton>\n</ui-stack>",
20544
+ "resizable": false,
20545
+ "bindings": "",
20546
+ "frameworks": {}
20547
+ },
20548
+ {
20549
+ "id": "@threadlabs/looma/ui-skeleton/03-loading-card",
20550
+ "name": "03-loading-card",
20551
+ "title": "Loading a profile",
20552
+ "description": "One status describes the work; the section stays busy until the application replaces its decorative placeholders. Compare the loaded card's avatar and text metrics.",
20553
+ "markup": "<ui-stack gap=\"m\">\n <ui-status-message kind=\"loading\">Loading a profile…</ui-status-message>\n <ui-grid>\n <ui-card as=\"section\" aria-label=\"Profile\" aria-busy=\"true\">\n <ui-cluster gap=\"s\">\n <ui-skeleton shape=\"circle\"></ui-skeleton>\n <ui-stack fill gap=\"none\">\n <ui-skeleton width=\"65%\"></ui-skeleton>\n <ui-skeleton width=\"45%\"></ui-skeleton>\n </ui-stack>\n </ui-cluster>\n <ui-stack gap=\"none\">\n <ui-skeleton></ui-skeleton>\n <ui-skeleton width=\"80%\"></ui-skeleton>\n </ui-stack>\n </ui-card>\n <ui-card as=\"section\" aria-label=\"Loaded profile\">\n <ui-cluster gap=\"s\">\n <ui-avatar name=\"Ada Lovelace\" decorative></ui-avatar>\n <ui-stack fill gap=\"none\">\n <ui-text weight=\"semibold\">Ada Lovelace</ui-text>\n <ui-text tone=\"secondary\">Mathematician</ui-text>\n </ui-stack>\n </ui-cluster>\n <ui-text>Notes on an analytical engine and the possibilities of computation.</ui-text>\n </ui-card>\n </ui-grid>\n</ui-stack>",
20554
+ "resizable": false,
20555
+ "bindings": "",
20556
+ "frameworks": {}
20557
+ },
20558
+ {
20559
+ "id": "@threadlabs/looma/ui-skeleton/04-animation",
20560
+ "name": "04-animation",
20561
+ "title": "Optional motion",
20562
+ "description": "Still by default. Opt in to a gentle pulse when it helps convey loading; reduced-motion preferences always keep it still.",
20563
+ "markup": "<ui-stack gap=\"s\">\n <ui-text tone=\"secondary\" size=\"sm\">Still</ui-text>\n <ui-skeleton width=\"75%\"></ui-skeleton>\n <ui-text tone=\"secondary\" size=\"sm\">Animated when motion is welcome</ui-text>\n <ui-skeleton animated width=\"75%\"></ui-skeleton>\n</ui-stack>",
20564
+ "resizable": false,
20565
+ "bindings": "",
20566
+ "frameworks": {}
20567
+ }
20568
+ ]
20569
+ },
20080
20570
  {
20081
20571
  "tag": "ui-slider",
20082
20572
  "package": "@threadlabs/looma",
@@ -0,0 +1,11 @@
1
+ import { componentRegistry } from "@nextwebwg/html-next/runtime";
2
+ /** Reflect navigation requests into this example's bounded, consumer-owned page window. */
3
+ export default function setup(root) {
4
+ const navigate = (event) => {
5
+ const page = event.detail.page;
6
+ const values = [...new Set([1, page - 1, page, page + 1, 10])].filter(value => value >= 1 && value <= 10).sort((a, b) => a - b);
7
+ componentRegistry.update(event.target, { page, pages: values.map(value => ({ value })), hasPrevious: page > 1, hasNext: page < 10 });
8
+ };
9
+ root.addEventListener("navigate", navigate);
10
+ return () => root.removeEventListener("navigate", navigate);
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.37.4",
3
+ "version": "0.37.6",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -129,6 +129,7 @@
129
129
  }
130
130
 
131
131
  :scope:where([data-component~="ui-button"]) {
132
+ --_button-square-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
132
133
  appearance: none;
133
134
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
134
135
  border-style: solid;
@@ -193,6 +194,7 @@
193
194
  }
194
195
 
195
196
  :scope:where([data-component~="ui-button"])[data-ui-button-state~="size=xs"] {
197
+ --_button-square-size: 1.5rem;
196
198
  min-block-size: 1.5rem;
197
199
  padding: calc(var(--ui-space-0-5) * 1.5) calc(var(--ui-space-1) * 1.25) !important;
198
200
  font-size: var(--ui-font-size-xs);
@@ -203,17 +205,25 @@
203
205
  }
204
206
 
205
207
  :scope:where([data-component~="ui-button"])[data-ui-button-state~="size=sm"] {
208
+ --_button-square-size: var(--ui-control-size-sm);
206
209
  min-block-size: var(--ui-control-size-sm);
207
210
  padding: var(--ui-control-inset-block-sm, var(--ui-space-1)) var(--ui-action-inset-sm, var(--ui-space-2)) !important;
208
211
  font-size: var(--ui-font-size-sm);
209
212
  }
210
213
 
211
214
  :scope:where([data-component~="ui-button"])[data-ui-button-state~="size=lg"] {
215
+ --_button-square-size: var(--ui-control-size-lg);
212
216
  min-block-size: var(--ui-control-size-lg);
213
217
  padding: var(--ui-control-inset-block-lg, var(--ui-space-3)) var(--ui-action-inset-lg, var(--ui-space-4)) !important;
214
218
  font-size: var(--ui-font-size-md);
215
219
  }
216
220
 
221
+ /* Short numeric and icon actions share a minimum box; large values remain readable. */
222
+ :scope:where([data-component~="ui-button"])[data-ui-button-state~="square"]:not([data-appearance="link"], [data-appearance="card"]) {
223
+ min-inline-size: var(--_button-square-size);
224
+ padding-inline: var(--ui-space-1) !important;
225
+ }
226
+
217
227
  /* Card actions inherit Button's palette and behavior; only their shared layout changes.
218
228
  The icon may contain any decorative composition. Empty icons remove their column. */
219
229
  :scope:where([data-component~="ui-button"])[data-appearance="card"] {
@@ -530,6 +540,8 @@
530
540
  @supports (text-box-trim: trim-both) {
531
541
  }
532
542
 
543
+ /* Short numeric and icon actions share a minimum box; large values remain readable. */
544
+
533
545
  /* Card actions inherit Button's palette and behavior; only their shared layout changes.
534
546
  The icon may contain any decorative composition. Empty icons remove their column. */
535
547
 
@@ -0,0 +1 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.69. Do not edit. */