@blukavantui/community 1.0.1 → 1.1.0

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 (160) hide show
  1. package/README.md +11 -5
  2. package/dist/build-audit.json +181 -53
  3. package/dist/checkbox.css +1 -0
  4. package/dist/checkbox.d.ts +2 -0
  5. package/dist/checkbox.js +1 -0
  6. package/dist/chunk-3PNBQVYS.js +1 -0
  7. package/dist/chunk-5ENZVZGF.js +0 -0
  8. package/dist/chunk-AL2ETLJV.js +1 -0
  9. package/dist/chunk-BN3PDE5G.js +0 -0
  10. package/dist/chunk-EOKNLCNS.js +1 -0
  11. package/dist/chunk-EPZGLHPD.js +0 -0
  12. package/dist/chunk-FNX33PDD.js +0 -0
  13. package/dist/chunk-GXHANADL.js +1 -0
  14. package/dist/chunk-HO6CYWED.js +0 -0
  15. package/dist/chunk-IJ62ILKE.js +0 -0
  16. package/dist/chunk-IO22GWON.js +0 -0
  17. package/dist/chunk-IZJN3EF7.js +1 -0
  18. package/dist/chunk-JVE6CXCJ.js +1 -0
  19. package/dist/chunk-MYVLBALF.js +1 -0
  20. package/dist/chunk-OPMD7QNV.js +1 -0
  21. package/dist/chunk-RWBLICYX.js +0 -0
  22. package/dist/chunk-RYD6RHRX.js +0 -0
  23. package/dist/chunk-UN2SLVFG.js +1 -0
  24. package/dist/chunk-VJVFHL6P.js +0 -0
  25. package/dist/chunk-XWXEH3SW.js +1 -0
  26. package/dist/chunk-YCLR3IE3.js +0 -0
  27. package/dist/columns2.css +1 -0
  28. package/dist/columns2.d.ts +2 -0
  29. package/dist/columns2.js +1 -0
  30. package/dist/columns3.css +1 -0
  31. package/dist/columns3.d.ts +2 -0
  32. package/dist/columns3.js +1 -0
  33. package/dist/columns4.css +1 -0
  34. package/dist/columns4.d.ts +2 -0
  35. package/dist/columns4.js +1 -0
  36. package/dist/content.js +1 -1
  37. package/dist/core.js +1 -1
  38. package/dist/data.css +63 -0
  39. package/dist/data.d.ts +1 -0
  40. package/dist/data.js +1 -1
  41. package/dist/date-picker.css +5 -5
  42. package/dist/date-picker.js +1 -1
  43. package/dist/date-range-picker.css +5 -5
  44. package/dist/date-range-picker.js +1 -1
  45. package/dist/date-time-picker.css +5 -5
  46. package/dist/date-time-picker.js +1 -1
  47. package/dist/draft-components.json +77 -0
  48. package/dist/feedback.js +1 -1
  49. package/dist/form-field.css +1 -0
  50. package/dist/form-field.d.ts +2 -0
  51. package/dist/form-field.js +1 -0
  52. package/dist/form-layout/choice.d.ts +15 -0
  53. package/dist/form-layout/layout.d.ts +12 -0
  54. package/dist/form-layout/select.d.ts +3 -0
  55. package/dist/form-layout/shared.d.ts +21 -0
  56. package/dist/form-layout/table.d.ts +20 -0
  57. package/dist/form-layout/text.d.ts +3 -0
  58. package/dist/form-layout/types.d.ts +151 -0
  59. package/dist/form-layout.css +62 -0
  60. package/dist/form-layout.d.ts +12 -0
  61. package/dist/form-layout.js +1 -0
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.js +1 -1
  64. package/dist/inputs.css +83 -20
  65. package/dist/inputs.d.ts +8 -0
  66. package/dist/inputs.js +1 -1
  67. package/dist/layout.css +63 -0
  68. package/dist/layout.d.ts +3 -0
  69. package/dist/layout.js +1 -1
  70. package/dist/native/date-picker.js +1 -1
  71. package/dist/native/date-range-picker.js +1 -1
  72. package/dist/native/date-time-picker.js +1 -1
  73. package/dist/native/form-layout.js +1 -0
  74. package/dist/native/time-picker.js +1 -1
  75. package/dist/native-components/form-layout.d.ts +1 -0
  76. package/dist/radio-button.css +1 -0
  77. package/dist/radio-button.d.ts +2 -0
  78. package/dist/radio-button.js +1 -0
  79. package/dist/radio-group.css +1 -0
  80. package/dist/radio-group.d.ts +2 -0
  81. package/dist/radio-group.js +1 -0
  82. package/dist/select.css +1 -0
  83. package/dist/select.d.ts +2 -0
  84. package/dist/select.js +1 -0
  85. package/dist/sizes.json +272 -90
  86. package/dist/styles.css +83 -20
  87. package/dist/switch.css +1 -0
  88. package/dist/switch.d.ts +2 -0
  89. package/dist/switch.js +1 -0
  90. package/dist/table.css +1 -0
  91. package/dist/table.d.ts +2 -0
  92. package/dist/table.js +1 -0
  93. package/dist/text-area.css +1 -0
  94. package/dist/text-area.d.ts +2 -0
  95. package/dist/text-area.js +1 -0
  96. package/dist/text-input.css +1 -0
  97. package/dist/text-input.d.ts +2 -0
  98. package/dist/text-input.js +1 -0
  99. package/dist/time-picker.css +5 -5
  100. package/dist/time-picker.js +1 -1
  101. package/docs/FORM-LAYOUT-ESSENTIALS.md +122 -0
  102. package/docs/PUBLISHING.md +129 -25
  103. package/draft-components.json +77 -0
  104. package/edition.json +44 -7
  105. package/npm-shrinkwrap.json +2 -2
  106. package/package.json +76 -10
  107. package/scripts/build.mjs +16 -8
  108. package/src/checkbox.ts +2 -0
  109. package/src/columns2.ts +2 -0
  110. package/src/columns3.ts +2 -0
  111. package/src/columns4.ts +2 -0
  112. package/src/data.ts +1 -0
  113. package/src/form-field.ts +2 -0
  114. package/src/form-layout/choice.ts +66 -0
  115. package/src/form-layout/layout.ts +40 -0
  116. package/src/form-layout/select.ts +97 -0
  117. package/src/form-layout/shared.ts +57 -0
  118. package/src/form-layout/table.ts +86 -0
  119. package/src/form-layout/text.ts +73 -0
  120. package/src/form-layout/types.ts +59 -0
  121. package/src/form-layout.ts +12 -0
  122. package/src/index.ts +2 -0
  123. package/src/inputs.ts +8 -0
  124. package/src/layout.ts +3 -0
  125. package/src/native-components/form-layout.ts +21 -0
  126. package/src/radio-button.ts +2 -0
  127. package/src/radio-group.ts +2 -0
  128. package/src/runtime/date-picker.js +21 -12
  129. package/src/runtime/date-range-picker.js +21 -12
  130. package/src/runtime/date-time-picker.js +21 -12
  131. package/src/runtime/time-picker.js +21 -12
  132. package/src/select.ts +2 -0
  133. package/src/switch.ts +2 -0
  134. package/src/table.ts +2 -0
  135. package/src/text-area.ts +2 -0
  136. package/src/text-input.ts +2 -0
  137. package/src/types.ts +0 -12
  138. package/styles/checkbox.css +1 -0
  139. package/styles/columns2.css +1 -0
  140. package/styles/columns3.css +1 -0
  141. package/styles/columns4.css +1 -0
  142. package/styles/date-picker.css +5 -5
  143. package/styles/date-range-picker.css +5 -5
  144. package/styles/date-time-picker.css +5 -5
  145. package/styles/form-field.css +1 -0
  146. package/styles/form-layout.css +62 -0
  147. package/styles/radio-button.css +1 -0
  148. package/styles/radio-group.css +1 -0
  149. package/styles/select.css +1 -0
  150. package/styles/switch.css +1 -0
  151. package/styles/table.css +1 -0
  152. package/styles/text-area.css +1 -0
  153. package/styles/text-input.css +1 -0
  154. package/styles/time-picker.css +5 -5
  155. package/test/form-layout.test.mjs +28 -0
  156. package/test/isolation.test.mjs +2 -2
  157. package/dist/chunk-2TCNAQC6.js +0 -1
  158. package/dist/chunk-CTLZIWMX.js +0 -1
  159. package/dist/chunk-MHHJZYXW.js +0 -1
  160. package/dist/chunk-XDYBNO4P.js +0 -1
package/dist/styles.css CHANGED
@@ -4523,7 +4523,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4523
4523
  .blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
4524
4524
  .blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
4525
4525
  .blu-picker__field {flex:1 1 180px;min-width:0;}
4526
- .blu-picker__field label,.blu-picker__select-field>span {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4526
+ .blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4527
4527
  .blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
4528
4528
  .blu-picker__field-control {position:relative;}
4529
4529
  .blu-picker__field-control>.blu-picker__input {padding-right:38px;}
@@ -4546,7 +4546,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4546
4546
  .blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
4547
4547
  .blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
4548
4548
  .blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
4549
- .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 72px 32px;align-items:end;gap:6px;margin-top:0;}
4549
+ .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
4550
4550
  .blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
4551
4551
  .blu-picker__select-field {min-width:0;}
4552
4552
  .blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
@@ -4571,8 +4571,8 @@ Keep bulk commands together in a wrapping row between the panels. */
4571
4571
  /* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
4572
4572
  .blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
4573
4573
  .blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
4574
- .blu-picker__dialog .blu-picker__select-field>span {font-size:11px;margin-bottom:2px;}
4575
- .blu-picker__calendar-nav .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4574
+ .blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
4575
+ .blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4576
4576
  .blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
4577
4577
  @media(pointer:coarse){
4578
4578
  .blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
@@ -4589,7 +4589,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4589
4589
  .blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
4590
4590
  .blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
4591
4591
  .blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
4592
- .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4592
+ .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4593
4593
  .blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4594
4594
  .blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
4595
4595
  .blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
@@ -4602,7 +4602,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4602
4602
  .blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
4603
4603
  .blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
4604
4604
  .blu-picker__field {flex:1 1 180px;min-width:0;}
4605
- .blu-picker__field label,.blu-picker__select-field>span {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4605
+ .blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4606
4606
  .blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
4607
4607
  .blu-picker__field-control {position:relative;}
4608
4608
  .blu-picker__field-control>.blu-picker__input {padding-right:38px;}
@@ -4625,7 +4625,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4625
4625
  .blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
4626
4626
  .blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
4627
4627
  .blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
4628
- .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 72px 32px;align-items:end;gap:6px;margin-top:0;}
4628
+ .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
4629
4629
  .blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
4630
4630
  .blu-picker__select-field {min-width:0;}
4631
4631
  .blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
@@ -4650,8 +4650,8 @@ Keep bulk commands together in a wrapping row between the panels. */
4650
4650
  /* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
4651
4651
  .blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
4652
4652
  .blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
4653
- .blu-picker__dialog .blu-picker__select-field>span {font-size:11px;margin-bottom:2px;}
4654
- .blu-picker__calendar-nav .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4653
+ .blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
4654
+ .blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4655
4655
  .blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
4656
4656
  @media(pointer:coarse){
4657
4657
  .blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
@@ -4668,7 +4668,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4668
4668
  .blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
4669
4669
  .blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
4670
4670
  .blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
4671
- .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4671
+ .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4672
4672
  .blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4673
4673
  .blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
4674
4674
  .blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
@@ -4681,7 +4681,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4681
4681
  .blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
4682
4682
  .blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
4683
4683
  .blu-picker__field {flex:1 1 180px;min-width:0;}
4684
- .blu-picker__field label,.blu-picker__select-field>span {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4684
+ .blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4685
4685
  .blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
4686
4686
  .blu-picker__field-control {position:relative;}
4687
4687
  .blu-picker__field-control>.blu-picker__input {padding-right:38px;}
@@ -4704,7 +4704,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4704
4704
  .blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
4705
4705
  .blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
4706
4706
  .blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
4707
- .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 72px 32px;align-items:end;gap:6px;margin-top:0;}
4707
+ .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
4708
4708
  .blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
4709
4709
  .blu-picker__select-field {min-width:0;}
4710
4710
  .blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
@@ -4729,8 +4729,8 @@ Keep bulk commands together in a wrapping row between the panels. */
4729
4729
  /* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
4730
4730
  .blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
4731
4731
  .blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
4732
- .blu-picker__dialog .blu-picker__select-field>span {font-size:11px;margin-bottom:2px;}
4733
- .blu-picker__calendar-nav .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4732
+ .blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
4733
+ .blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4734
4734
  .blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
4735
4735
  @media(pointer:coarse){
4736
4736
  .blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
@@ -4747,7 +4747,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4747
4747
  .blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
4748
4748
  .blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
4749
4749
  .blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
4750
- .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4750
+ .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4751
4751
  .blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4752
4752
  .blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
4753
4753
  .blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
@@ -4760,7 +4760,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4760
4760
  .blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
4761
4761
  .blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
4762
4762
  .blu-picker__field {flex:1 1 180px;min-width:0;}
4763
- .blu-picker__field label,.blu-picker__select-field>span {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4763
+ .blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
4764
4764
  .blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
4765
4765
  .blu-picker__field-control {position:relative;}
4766
4766
  .blu-picker__field-control>.blu-picker__input {padding-right:38px;}
@@ -4783,7 +4783,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4783
4783
  .blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
4784
4784
  .blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
4785
4785
  .blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
4786
- .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 72px 32px;align-items:end;gap:6px;margin-top:0;}
4786
+ .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
4787
4787
  .blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
4788
4788
  .blu-picker__select-field {min-width:0;}
4789
4789
  .blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
@@ -4808,8 +4808,8 @@ Keep bulk commands together in a wrapping row between the panels. */
4808
4808
  /* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
4809
4809
  .blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
4810
4810
  .blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
4811
- .blu-picker__dialog .blu-picker__select-field>span {font-size:11px;margin-bottom:2px;}
4812
- .blu-picker__calendar-nav .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4811
+ .blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
4812
+ .blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4813
4813
  .blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
4814
4814
  @media(pointer:coarse){
4815
4815
  .blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
@@ -4826,7 +4826,7 @@ Keep bulk commands together in a wrapping row between the panels. */
4826
4826
  .blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
4827
4827
  .blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
4828
4828
  .blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
4829
- .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4829
+ .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
4830
4830
  .blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
4831
4831
  .blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
4832
4832
  .blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
@@ -8880,3 +8880,66 @@ beside the live host/List, never inside a JavaScript-owned host. */
8880
8880
 
8881
8881
  /* Service Studio caption is hidden once the owned grid has initialized. */
8882
8882
  .blu-community-block:has([data-blu-community-ready]) > .blu-community-preview { display: none; }
8883
+
8884
+ /* Community Form & Layout Essentials — local draft; no OutSystems UI selectors. */
8885
+ .blu-field,.blu-columns,.blu-table{box-sizing:border-box;min-width:0;color:var(--bluui-text,#182230);font-family:var(--blu-font-family,Inter,system-ui,sans-serif);font-size:14px}
8886
+ .blu-field *,.blu-columns *,.blu-table *{box-sizing:border-box}
8887
+ .blu-field [hidden],.blu-table [hidden]{display:none!important}
8888
+ .blu-field{--blu-field-height:42px;--blu-field-padding:12px;display:flex;flex-direction:column;gap:7px;border:0;padding:0;margin:0;min-inline-size:0}
8889
+ .blu-field--small{--blu-field-height:34px;--blu-field-padding:9px;font-size:13px}.blu-field--large{--blu-field-height:50px;--blu-field-padding:15px;font-size:16px}
8890
+ .blu-field__label{font-weight:600;line-height:1.5;padding:0;margin:0 0 2px}.blu-field__body{min-width:0}
8891
+ .blu-field__help,.blu-choice__description,.blu-field__count{font-size:12px;color:var(--bluui-text-muted,#5c6b80);line-height:1.5}.blu-field__error{color:var(--bluui-color-error-text,#b42318);font-size:12px;line-height:1.5}.blu-field__count{text-align:end;margin-top:5px;font-variant-numeric:tabular-nums}
8892
+ .blu-text,.blu-textarea,.blu-select__trigger{border:1px solid var(--bluui-control-border,#7b8799);border-radius:var(--blu-radius-md,8px);background:var(--bluui-surface,#fff);color:inherit;transition:border-color .12s,box-shadow .12s}
8893
+ .blu-text{display:flex;align-items:center;gap:8px;min-height:var(--blu-field-height);padding:0 var(--blu-field-padding)}
8894
+ .blu-text__input{width:100%;min-width:0;border:0!important;box-shadow:none!important;outline:none!important;background:transparent!important;color:inherit;padding:9px 0!important;font:inherit;line-height:1.5;height:auto}
8895
+ .blu-text__input::placeholder,.blu-textarea::placeholder{color:var(--bluui-text-muted,#5c6b80);opacity:1}
8896
+ .blu-text:focus-within,.blu-textarea:focus-visible,.blu-select__trigger:focus-visible{border-color:var(--bluui-primary,#4f46e5);outline:2px solid var(--bluui-primary,#4f46e5);outline-offset:2px}
8897
+ .blu-text__adornment{display:inline-flex;flex:none;gap:6px;align-items:center;color:var(--bluui-text-muted,#5c6b80);white-space:nowrap}.blu-text__adornment img{width:24px;height:24px;object-fit:contain;border-radius:4px}
8898
+ .blu-text__action{display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:4px;background:transparent;color:var(--bluui-primary,#4f46e5);font:inherit;font-size:12px;font-weight:600;min-width:26px;min-height:30px;cursor:pointer;white-space:nowrap;padding:3px}
8899
+ .blu-text__action:hover{background:var(--bluui-hover,#f0f2f7)}
8900
+ .blu-field button:focus-visible,.blu-table button:focus-visible,.blu-table__scroll:focus-visible{outline:2px solid var(--bluui-primary,#4f46e5);outline-offset:3px}
8901
+ .blu-textarea{display:block;width:100%;min-height:var(--blu-field-height);padding:10px var(--blu-field-padding);font:inherit;line-height:1.6}
8902
+ .blu-field[data-invalid=true] .blu-text,.blu-field[data-invalid=true] .blu-textarea,.blu-field[data-invalid=true] .blu-select__trigger{border-color:var(--bluui-color-error-text,#b42318)}
8903
+ .blu-field[data-disabled=true]{opacity:.6}.blu-field input:disabled,.blu-field textarea:disabled,.blu-field button:disabled{cursor:not-allowed}
8904
+ .blu-field input[readonly],.blu-field textarea[readonly]{cursor:default}
8905
+ .blu-choice{display:flex;align-items:center;position:relative;gap:10px;min-height:32px;cursor:pointer;line-height:1.5}.blu-choice__input{position:absolute;inline-size:1px;block-size:1px;clip-path:inset(50%);overflow:hidden;white-space:nowrap;opacity:0}
8906
+ .blu-choice__mark{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:19px;height:19px;border:1.5px solid var(--bluui-control-border,#7b8799);border-radius:5px;background:var(--bluui-surface,#fff);color:var(--bluui-on-primary,#fff)}
8907
+ .blu-choice__input:checked+.blu-choice__mark,.blu-choice__input:indeterminate+.blu-choice__mark{background:var(--bluui-primary,#4f46e5);border-color:var(--bluui-primary,#4f46e5)}
8908
+ .blu-choice--checkbox .blu-choice__input:checked+.blu-choice__mark:after{content:'';width:5px;height:9px;border:solid currentColor;border-width:0 2px 2px 0;transform:translateY(-1px) rotate(45deg)}
8909
+ .blu-choice__input:indeterminate+.blu-choice__mark:after{content:'';width:9px;height:2px;background:currentColor;transform:none;border:0}
8910
+ .blu-choice__input:focus-visible+.blu-choice__mark{outline:2px solid var(--bluui-primary,#4f46e5);outline-offset:3px}
8911
+ .blu-choice:has(input:disabled){opacity:.6;cursor:not-allowed}.blu-field[data-disabled=true] .blu-choice:has(input:disabled){opacity:1}
8912
+ .blu-choice--radio .blu-choice__mark{border-radius:50%}.blu-choice--radio .blu-choice__input:checked+.blu-choice__mark:after{content:'';width:7px;height:7px;border-radius:50%;background:currentColor}
8913
+ .blu-choice--switch .blu-choice__mark{width:38px;height:22px;border-radius:20px;background:var(--bluui-control-border,#7b8799);padding:2px;justify-content:flex-start}
8914
+ .blu-choice--switch .blu-choice__mark:after{content:'';height:16px;width:16px;background:#fff;border-radius:50%;transition:transform .15s}
8915
+ .blu-choice--switch .blu-choice__input:checked+.blu-choice__mark:after{transform:translateX(14px)}.blu-choice--switch .blu-choice__input:checked+.blu-choice__mark{background:var(--bluui-primary,#4f46e5)}
8916
+ .blu-choice__state{margin-inline-start:auto;font-size:12px;color:var(--bluui-text-muted,#5c6b80)}.blu-choice__description{display:block}
8917
+ .blu-radio-group{display:flex;flex-direction:column;gap:10px}.blu-radio-group--horizontal{flex-direction:row;flex-wrap:wrap;gap:12px 24px}
8918
+ .blu-select{position:relative;display:flex;gap:5px}.blu-select__native{position:absolute;width:1px;height:1px;opacity:0;clip-path:inset(50%);pointer-events:none}
8919
+ .blu-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0;min-height:var(--blu-field-height);width:100%;padding:9px var(--blu-field-padding);font:inherit;text-align:start;cursor:pointer}
8920
+ .blu-select__trigger:after{content:'';width:7px;height:7px;border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:translateY(-2px) rotate(45deg);flex-shrink:0}.blu-select__trigger[data-placeholder=true]{color:var(--bluui-text-muted,#5c6b80)}
8921
+ .blu-select__popup{box-sizing:border-box;position:absolute;inset:calc(100% + 6px) 0 auto;z-index:1000;max-height:320px;overflow:auto;margin:0;padding:6px;border:1px solid var(--bluui-border-strong,#b8c4d4);border-radius:10px;background:var(--bluui-surface,#fff);box-shadow:var(--bluui-menu-shadow,0 10px 30px #17203326);color:var(--bluui-text,#182230);font:inherit}
8922
+ .blu-select__search{width:100%;min-height:38px;padding:8px 10px;border:1px solid var(--bluui-control-border,#7b8799);border-radius:6px;background:var(--bluui-surface,#fff);color:inherit;font:inherit;margin-bottom:5px;outline-offset:2px}
8923
+ .blu-select__option{padding:9px 10px;border-radius:5px;cursor:pointer;line-height:1.5}.blu-select__option[aria-selected=true]{font-weight:600;color:var(--bluui-primary,#4f46e5)}.blu-select__option[data-active=true]{background:var(--bluui-selected,#e9e6ff)}.blu-select__option[aria-disabled=true]{opacity:.5;cursor:not-allowed}
8924
+ .blu-columns{display:grid;grid-template-columns:var(--blu-columns-tracks,1fr 1fr);gap:var(--blu-columns-gap,24px)}.blu-columns__column{min-width:0;display:flex;flex-direction:column;gap:20px}
8925
+ @media(max-width:479px){.blu-columns--stack-small{grid-template-columns:minmax(0,1fr)}}
8926
+ @media(max-width:767px){.blu-columns--stack-medium{grid-template-columns:minmax(0,1fr)}}
8927
+ @media(max-width:1023px){.blu-columns--stack-large{grid-template-columns:minmax(0,1fr)}}
8928
+ .blu-table{border:1px solid var(--bluui-border,#e2e8f0);border-radius:12px;background:var(--bluui-surface,#fff);overflow:hidden}
8929
+ .blu-table__scroll{overflow:auto}.blu-table table{width:100%;border-collapse:collapse;font:inherit;text-align:start}.blu-table caption{text-align:start;padding:18px;font-weight:600;font-size:15px}
8930
+ .blu-table th{font-size:12px;color:var(--bluui-text-muted,#5c6b80);background:var(--bluui-surface-muted,#f7f8fb);font-weight:600;white-space:nowrap}
8931
+ .blu-table th,.blu-table td{padding:14px 18px;border-top:1px solid var(--bluui-border,#e2e8f0);line-height:1.5}
8932
+ .blu-table[data-density=Compact] th,.blu-table[data-density=Compact] td{padding:8px 12px}
8933
+ .blu-table[data-striped=true] tbody tr:nth-child(even){background:var(--bluui-surface-muted,#f7f8fb)}
8934
+ .blu-table__sort{font:inherit;font-weight:600;color:inherit;background:transparent;border:0;padding:0;cursor:pointer;display:inline-flex;align-items:center;gap:12px}
8935
+ .blu-table__empty{text-align:center!important;height:140px;color:var(--bluui-text-muted,#5c6b80)}
8936
+ .blu-table__footer{display:flex;align-items:center;gap:8px;padding:12px 18px;border-top:1px solid var(--bluui-border,#e2e8f0);font-size:12px;flex-wrap:wrap}.blu-table__footer>span{margin-inline-end:auto;color:var(--bluui-text-muted,#5c6b80)}
8937
+ .blu-table-button{border:1px solid var(--bluui-border-strong,#b8c4d4);border-radius:6px;padding:6px 10px;background:var(--bluui-surface,#fff);font:inherit;font-size:12px;color:var(--bluui-text,#182230);cursor:pointer;min-height:30px;white-space:nowrap}.blu-table-button:hover{background:var(--bluui-hover,#f0f2f7)}.blu-table-button:disabled{opacity:.5;cursor:not-allowed}.blu-table__actions{display:flex;gap:6px}
8938
+ @media(prefers-reduced-motion:reduce){.blu-field *{transition:none!important}}
8939
+ @media(forced-colors:active){.blu-choice__mark{forced-color-adjust:none;border-color:ButtonText;background:Canvas;color:HighlightText}.blu-choice__input:checked+.blu-choice__mark,.blu-choice__input:indeterminate+.blu-choice__mark{background:Highlight;border-color:Highlight}.blu-select__option[data-active=true]{outline:2px solid Highlight}.blu-choice--switch .blu-choice__mark:after{background:ButtonText}.blu-choice--switch .blu-choice__input:checked+.blu-choice__mark:after{background:HighlightText}}
8940
+
8941
+ /* Equal height is row-scoped; stacked columns retain their content height. */
8942
+ .blu-columns.blu-columns--equal-height{align-items:stretch}
8943
+ .blu-columns--equal-height > .blu-columns__column > :only-child{flex:1 1 auto}
8944
+ .blu-columns--equal-height > .blu-columns__column > [data-placeholder]{display:flex;flex-direction:column}
8945
+ .blu-columns--equal-height > .blu-columns__column > [data-placeholder] > :only-child{flex:1 1 auto}
@@ -0,0 +1 @@
1
+ @import './form-layout.css';
@@ -0,0 +1,2 @@
1
+ export { createSwitch } from './form-layout/choice.js';
2
+ export type * from './form-layout/types.js';
package/dist/switch.js ADDED
@@ -0,0 +1 @@
1
+ import"./chunk-EPZGLHPD.js";import{b as a}from"./chunk-GXHANADL.js";import"./chunk-EOKNLCNS.js";export{a as createSwitch};
package/dist/table.css ADDED
@@ -0,0 +1 @@
1
+ @import './form-layout.css';
@@ -0,0 +1,2 @@
1
+ export { createTable } from './form-layout/table.js';
2
+ export type * from './form-layout/types.js';
package/dist/table.js ADDED
@@ -0,0 +1 @@
1
+ import{a}from"./chunk-IZJN3EF7.js";import"./chunk-EOKNLCNS.js";export{a as createTable};
@@ -0,0 +1 @@
1
+ @import './form-layout.css';
@@ -0,0 +1,2 @@
1
+ export { createTextArea } from './form-layout/text.js';
2
+ export type * from './form-layout/types.js';
@@ -0,0 +1 @@
1
+ import"./chunk-YCLR3IE3.js";import{b as a}from"./chunk-AL2ETLJV.js";import"./chunk-EOKNLCNS.js";export{a as createTextArea};
@@ -0,0 +1 @@
1
+ @import './form-layout.css';
@@ -0,0 +1,2 @@
1
+ export { createTextInput } from './form-layout/text.js';
2
+ export type * from './form-layout/types.js';
@@ -0,0 +1 @@
1
+ import"./chunk-RWBLICYX.js";import{a}from"./chunk-AL2ETLJV.js";import"./chunk-EOKNLCNS.js";export{a as createTextInput};
@@ -6,7 +6,7 @@
6
6
  .blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
7
7
  .blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
8
8
  .blu-picker__field {flex:1 1 180px;min-width:0;}
9
- .blu-picker__field label,.blu-picker__select-field>span {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
9
+ .blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
10
10
  .blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
11
11
  .blu-picker__field-control {position:relative;}
12
12
  .blu-picker__field-control>.blu-picker__input {padding-right:38px;}
@@ -29,7 +29,7 @@
29
29
  .blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
30
30
  .blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
31
31
  .blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
32
- .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 72px 32px;align-items:end;gap:6px;margin-top:0;}
32
+ .blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
33
33
  .blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
34
34
  .blu-picker__select-field {min-width:0;}
35
35
  .blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
@@ -54,8 +54,8 @@
54
54
  /* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
55
55
  .blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
56
56
  .blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
57
- .blu-picker__dialog .blu-picker__select-field>span {font-size:11px;margin-bottom:2px;}
58
- .blu-picker__calendar-nav .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
57
+ .blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
58
+ .blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
59
59
  .blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
60
60
  @media(pointer:coarse){
61
61
  .blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
@@ -72,7 +72,7 @@
72
72
  .blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
73
73
  .blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
74
74
  .blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
75
- .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-field>span {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
75
+ .blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
76
76
  .blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
77
77
  .blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
78
78
  .blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
@@ -1 +1 @@
1
- import{a}from"./chunk-XDYBNO4P.js";import"./chunk-MEEQNPGM.js";import"./chunk-5TEIXA4R.js";import"./chunk-SDMH2EVD.js";export{a as createTimePicker};
1
+ import{a}from"./chunk-JVE6CXCJ.js";import"./chunk-MEEQNPGM.js";import"./chunk-5TEIXA4R.js";import"./chunk-SDMH2EVD.js";export{a as createTimePicker};
@@ -0,0 +1,122 @@
1
+ # Community Form & Layout Essentials — local draft
2
+
3
+ This is unreleased development work. The npm and native 1.0.1 releases do not contain these additions. No version has been changed and no package, website, or native module has been published. `edition.json` continues to describe the existing release; `draft-components.json` explicitly tracks this batch. Native source preparation is not proof of Service Studio editor or runtime behavior.
4
+
5
+ ## Local preview and build
6
+
7
+ For the standard documentation playgrounds, use the local site at http://127.0.0.1:3384/components/text-input?platform=web#playground. All 12 additions appear in the **Form inputs**, **Layouts**, and **Data** sidebar groups. Existing inputs share **Form inputs** with the new controls; **Form builder** stays separate, with the shared Properties, Examples, Code and API tabs. Regenerate their local metadata with `node scripts/build-essentials-preview.mjs` from `bluui-site` after changing contracts.
8
+
9
+ For the separate composed-workflow example and component test harness, from `bluui-community`, run `npm run check`, `npm run build`, `npm test`, then `npm run preview:essentials`. Open http://127.0.0.1:3387/. The preview is bound to loopback only. The sample request form stores its rows in page memory. Run its component checks for browser interaction coverage. Source lives in `src/form-layout/`; the combined web package synchronizes these files from Community before building. Do not edit the generated web copies.
10
+
11
+ ## Components
12
+
13
+ | Component / factory | Purpose and options |
14
+ | --- | --- |
15
+ | Checkbox / `createCheckbox` | `Checked`, `Indeterminate`, `Label`, `Description`, `Required`, `Disabled`, `ReadOnly`, submitted `Value`; `Change(checked)` |
16
+ | Text Input / `createTextInput` | `Value`, `Type` (text, email, password, search, tel, url), `Placeholder`, `MaxLength`, `Autocomplete`, `Leading`, `Trailing`, `Clearable`, `RevealPassword`; `Change(value)`, `Action(key,value)` |
17
+ | Text Area / `createTextArea` | `Value`, `Rows`, `MaxLength`, `AutoGrow`, `MaxHeight`, `ShowCount`; `Change(value)` |
18
+ | Radio Button / `createRadioButton` | A single radio; share `Name` to form a native group, assign distinct `Value`; `Checked`, `Change(checked)` |
19
+ | Radio Group / `createRadioGroup` | `Options`, `Value`, `Direction` (Horizontal or Vertical), per-option descriptions/disabled state; `Change(value)` |
20
+ | Switch / `createSwitch` | `Checked`, `OnText`, `OffText`; `Change(checked)`; consumer owns persistence |
21
+ | Select / `createSelect` | Custom single-select listbox; `Options`, `Value`, `Placeholder`, `Clearable`, `Searchable`; `Change(value)` |
22
+ | Form Field / `createFormField` | Label, required marker, description, error, and a consumer-owned `Control` element. Preserves its previous ARIA attributes on destroy. Validation and disabled state of a consumer control remain consumer-owned. |
23
+ | Columns2 / `createColumns2` | Equal, OneThirdTwoThirds, TwoThirdsOneThird, OneQuarterThreeQuarters, ThreeQuartersOneQuarter |
24
+ | Columns3 / `createColumns3` | Equal or WideCenter |
25
+ | Columns4 / `createColumns4` | Equal |
26
+ | Table / `createTable` | Semantic HTML table; columns, rows, optional single-column sort and pagination, row-action callbacks, loading and empty states |
27
+
28
+ `src/form-layout/types.ts` is the complete typed web contract. All factory calls accept a host element and options; controls and the table accept events as a separate third argument. Fields share `Id` (set at creation), `Name`, `Label`, `Description`, `Error`, `Required`, `Disabled`, `ReadOnly`, `Size` (Small/Medium/Large), and `ExtendedClass`. Use a visible label. Setting `Error` supplies a custom validity message; clear it with `update({Error: ''})` after correcting application validation.
29
+
30
+ ## Use locally
31
+
32
+ Use a local link or these local build outputs; installing npm 1.0.1 will not fetch draft components. In a consuming app that links this workspace package:
33
+
34
+ ```ts
35
+ import {createTextInput} from '@blukavantui/community/text-input';
36
+ import {createSelect} from '@blukavantui/community/select';
37
+ import {createColumns2} from '@blukavantui/community/columns2';
38
+ import '@blukavantui/community/theme.css';
39
+ import '@blukavantui/community/form-layout.css';
40
+
41
+ const columns = createColumns2(host, {Ratio: 'OneThirdTwoThirds', Gap: 24});
42
+ const name = createTextInput(columns.columns[0], {
43
+ Name: 'name', Label: 'Customer name', Required: true,
44
+ Leading: {Kind: 'Image', Src: '/assets/company.svg', Alt: 'Company'},
45
+ Trailing: {Kind: 'Action', Text: 'Find', Label: 'Find customer', Key: 'find'},
46
+ }, {Change(value) { draft.name = value; }, Action(key, value) { findCustomer(value); }});
47
+ const team = createSelect(columns.columns[1], {
48
+ Name: 'team', Label: 'Team', Searchable: true, Clearable: true,
49
+ Options: [{Value: 'operations', Label: 'Operations'}],
50
+ });
51
+ // Later: name.update({Error: 'Enter a customer name.'});
52
+ // Cleanup children before their layout: name.destroy(); team.destroy(); columns.destroy();
53
+ ```
54
+
55
+ Text adornments accept `{Kind:'Text',Text}`, icons accept `{Kind:'Icon',Text,Label?}`, images accept `{Kind:'Image',Src,Alt}`, and actions accept `{Kind:'Action',Text,Label,Key}`. Image URLs must be HTTP(S) or relative URLs. Empty alt text is appropriate for decorative images. Adornments are rendered as text/DOM, never interpreted as HTML. Images are sized consistently on either side. For paragraphs with a large image on the left/right, use the existing `SplitSection` component; the preview includes an interactive example.
56
+
57
+ Fields expose `element`, `update(patch)`, `getValue()`, `reset()`, `focus()`, `validate()`, and `destroy()`. Individual controls also expose `control`, the actual input/textarea/select. RadioGroup provides a group handle rather than one control. Programmatic updates and reset do not emit Change; user interactions do. Reset restores the value given at creation, while preserving updated configuration. A canceled native form reset is respected. Mount inside the final form so the reset listener attaches to the correct owner. Use `update()` for programmatic changes; direct DOM property assignments do not synchronize component state unless an input/change event is dispatched.
58
+
59
+ The Select uses a custom popup, keyboard navigation, type-ahead, optional search, disabled-option skipping, Escape, outside click, and a native select for FormData and constraint validation. Only its custom trigger is exposed to assistive technology. Empty string is reserved for the placeholder; option values must be unique and non-empty. Read-only Select values should be supplied by the consumer. The popup uses the browser top layer when available and an in-place fallback otherwise.
60
+
61
+ RadioGroup uses standard radio inputs, so arrow keys follow browser radio navigation. Read-only controls reject user changes. A read-only group should also have an assigned value. Disabled controls do not submit through FormData. Checkbox indeterminate state is a visual/semantic mixed state; the checked value determines form submission.
62
+
63
+ Columns expose `columns` (two/three/four real content elements), `element`, `update`, and `destroy`. Append existing content to the slots and update proportions without replacing those nodes. `Gap` is 0–96px (24 default); `Align` is Start/Center/End/Stretch. `EqualHeight` defaults to false. Enable it to stretch each column and its single content wrapper to the tallest content within that row; it overrides Align while enabled. Wrap multiple widgets in one outer card/container when that card should fill the height. Stacked rows retain natural content heights. `StackAt` is Small (below 480px), Medium (below 768px, default), or Large (below 1024px). Columns stack in source order. Destroy child component instances before their layout to release their listeners.
64
+
65
+ ## Table versus Grid Basic
66
+
67
+ Table is for straightforward record lists: semantic headers, optional client sorting, optional paging, and named row actions. It has no grid engine. Grid Basic remains the choice for column filters, column resizing, automatic sizing, or grid-style selection. FormBuilder and FormRenderer remain Pro; this batch adds foundational controls, not a form designer.
68
+
69
+ ```ts
70
+ import {createTable} from '@blukavantui/community/table';
71
+ const table = createTable(host, {
72
+ Caption: 'Service requests', RowKey: 'Id', PageSize: 10,
73
+ Rows: [{Id: 'REQ-1', Name: 'Equipment setup', Quantity: 2}],
74
+ Columns: [
75
+ {Key: 'Id', Header: 'Request', Sortable: true},
76
+ {Key: 'Name', Header: 'Title'},
77
+ {Key: 'Quantity', Header: 'Items', Align: 'Right', Sortable: true},
78
+ ],
79
+ Actions: [{Key: 'view', Label: 'View'}],
80
+ }, {RowAction(key, row) { openRequest(row.Id); }});
81
+ // table.update({Rows: refreshedRows, Loading: false});
82
+ // table.update({Loading: true}); table.destroy();
83
+ ```
84
+
85
+ Table columns accept `Key`, `Header`, `Sortable`, `Align`, and optional text-only `Format(value,row)`. Sorting uses the raw cell value, never the displayed format. Numbers sort numerically; other values use locale-aware natural string ordering; null/undefined remain last in either direction. Paging is one-based and clamped after row updates. Omit PageSize for an unpaged list. `Density` is Compact/Comfortable; `Striped` is optional. `SortKey`, `SortDirection`, `Page`, `Loading`, `EmptyMessage`, and `Caption` are updateable. Events: `RowAction(key,row)`, `SortChanged(key,direction)`, `PageChanged(page)`. Row actions may supply `Disabled: true` or a web-only `Disabled(row)` predicate. RowKey makes repeated action names accessible and preserves focus across updates. The application owns loading, persistence, and routing; the component makes no network requests.
86
+
87
+ ## Native local implementation and verification boundary
88
+
89
+ Eighteen public native blocks are implemented and merged into the local Service Studio editors for `BluKavantUi_Community_Inputs`, `BluKavantUi_Community_Layout`, and `BluKavantUi_Community_Data`, under `Essentials`. Each block has a custom icon. Local OML review copies, original backups, model-edit source, validation results, and dependency inventories are saved in `native-builds/FormLayoutEssentials20261022/`. These are unpublished development copies; the released OMLs and npm archives are unchanged.
90
+
91
+ All three producers pass Service Studio validation with zero errors and only their two pre-existing license/notice resource warnings. The actual **Remove Unused Dependencies** command was run on each producer; all reported no dependencies to remove. Remaining references are `(System)` and, for Inputs/Data, `BluKavantUi_Community_Core`. There is no OutSystems UI or Material UI dependency. Platform Container, Expression, Image, and Placeholder widgets support editor display; they are distinct from the OutSystems UI producer.
92
+
93
+ Columns2/3/4 use real, editable `Column1`…`Column4` placeholders and CSS layout, with editor-only boundaries/minimum height. Their dynamic `Ratio` input affects runtime; Service Studio does not resolve that instance argument in the canvas. Choose a fixed preset when the proportions must be visible while designing:
94
+
95
+ | Native block | Visible proportions |
96
+ | --- | --- |
97
+ | Columns2, Columns3, Columns4 | Two, three or four equal columns |
98
+ | Columns2OneThird | 1 : 2 |
99
+ | Columns2TwoThirds | 2 : 1 |
100
+ | Columns2OneQuarter | 1 : 3 |
101
+ | Columns2ThreeQuarters | 3 : 1 |
102
+ | Columns3WideCenter | 1 : 2 : 1 |
103
+
104
+ The five presets accept `EqualHeight`, `Gap`, `Align`, `StackAt`, and `ExtendedClass`; they have no `Ratio` input. These dynamic settings resolve at runtime, while the editor displays the default spacing/alignment. All eight arrangements and an equal two-column layout nested inside a 1:2 layout were visually checked in the actual `ColumnsPreview` canvas. Each grid now owns its tracks, so nested columns do not inherit the parent's proportions. Empty Columns2 placeholders were also visually checked. Browser responsive stacking was checked at 390px; do not treat that as a compiled native consumer check.
105
+
106
+ Native TextInput offers `LeadingImageUrl`, `LeadingImageAlt`, `LeadingText`, `TrailingImageUrl`, `TrailingImageAlt`, and `TrailingText`. An image takes precedence over text; text takes precedence over the corresponding advanced `LeadingJson`/`TrailingJson` adornment. Advanced JSON supports the same icon/action contract as the web component. Images do not modify the field value. **Service Studio displays generic expression/image previews for dynamic block arguments; it does not show the passed image URL as the final image.**
107
+
108
+ For images visible and editable in the canvas, use the new native `InputGroup` block:
109
+
110
+ 1. Put a TextInput in its `Control` placeholder, with its accessible `Label` set.
111
+ 2. Put ordinary Image widgets in `Leading`, `Trailing`, or both. Set their actual image resource or literal URL and meaningful alt text (empty alt for decoration).
112
+ 3. Keep label, help, errors and validation on TextInput. Use an outer FormField only when you can supply the actual focusable input ID; the referenced Block ID identifies a wrapper, not the input.
113
+
114
+ InputGroup keeps the consumer-owned widgets in place; no JavaScript moves or clones them. Its CSS aligns the side images and removes the inner input border. The private `TextInputPreview` canvas was visually checked with real images on the left, right, and both sides. The text value still appears as Service Studio's expression preview. InputGroup and the five proportion presets are native composition helpers, not additional web factories; the web TextInput and Columns APIs already provide these options.
115
+
116
+ Native RadioGroup/Select take `OptionsJson` containing an array of `{Value,Label,Description?,Disabled?}`. Table takes `ColumnsJson`, `RowsJson`, and `ActionsJson`; columns require `Key` and `Header`, and actions require `Key` and `Label`. Supply at least one column. Native JSON cannot contain web formatter/predicate functions; format values before serialization, and use Boolean `Disabled` for actions. RowAction emits `Key` and serialized `RowJson`; sorting/paging emit their selected key/direction/page. JSON is parsed on both creation and updates; malformed JSON reports OnError.
117
+
118
+ OnReady and OnParametersChanged synchronize each control; OnDestroy disposes it. The local browser harness runs the exact generated native action scripts to verify mounting, image arguments, callbacks, JSON updates, disposal, and FormField ARIA restoration. Native FormField's `ControlId` must identify the actual input, not an enclosing block. It adds label/help/error associations while preserving consumer-owned attributes.
119
+
120
+ Consumers own values and application validation: assign the returned OnChange value to the variable passed into the block, and pass application validation messages through `Error`. These custom HTML controls do **not** automatically register with OutSystems `Form.Valid`; the consumer must validate its model before saving. Browser constraint validation and the web `validate()` API remain available for ordinary HTML forms.
121
+
122
+ No running OutSystems consumer was published or exercised. Runtime integration in a compiled OutSystems application remains a required pre-release check once publication is authorized. No dependency refresh or publication of the existing demo consumers was performed. FormBuilder/FormRenderer remain Pro.
@@ -1,25 +1,129 @@
1
- # Community npm publication handover
2
-
3
- This package is part of the reviewed 1.0.1 Community npm batch. Publication needs
4
- Jason's explicit approval. Preparing or running checks does not publish anything.
5
-
6
- The scope is exactly @blukavantui/community and @blukavantui/charts-community.
7
- Publish Community first, then Charts Community, whose dependency is ^1.0.1.
8
- Pro and Charts Pro remain licensed website downloads and are excluded.
9
-
10
- Publish the reviewed tarballs, not an arbitrary source directory or workspace.
11
- Compare their SHA-256 and npm SHA-512 integrity to the release review manifest.
12
- Confirm the publishing account can publish under the blukavantui organization.
13
- Use npm's normal interactive login and 2FA; never place credentials in packages.
14
- Recheck that the selected name/version is unpublished immediately before release.
15
-
16
- After approval, use explicit --access public and --registry=https://registry.npmjs.org/.
17
- Registry verification and a fresh install of both exact versions must follow.
18
- Website instructions and download links remain a separately approved deployment.
19
- The existing website tarballs retain their bytes; this npm batch changes package
20
- metadata/documentation and removes Charts folder-sync copies, not component code.
21
-
22
- References:
23
- - https://docs.npmjs.com/cli/v11/commands/npm-publish/
24
- - https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/
25
- - https://docs.npmjs.com/trusted-publishers/
1
+ # Publishing BluKavantUI Community to npm
2
+
3
+ This guide prepares and publishes the Web package `@blukavantui/community`.
4
+ It does not publish native OutSystems modules or deploy the website.
5
+
6
+ ## What Jason needs to set up
7
+
8
+ 1. Create or sign into your personal account at <https://www.npmjs.com/signup>,
9
+ verify your email, and enable two-factor authentication. Keep account recovery
10
+ codes somewhere safe; do not place credentials in this project.
11
+ 2. Create or obtain access to the `blukavantui` npm organization. Its scope must
12
+ match the package name. A package-name 404 does not prove the organization name
13
+ is available. Confirm ownership in the npm website and give your publishing
14
+ account permission to publish public packages under that organization.
15
+ 3. Review `LICENSE.txt` version 1.2. It adds the official npm source and service
16
+ provider distribution rights while preserving the Community use model and
17
+ third-party rights. The package remains source available under a custom license.
18
+ 4. Finish the component changes intended for this release and select the version.
19
+ Preparing the license, README and release checks does not require freezing
20
+ development; publishing does require choosing the exact source snapshot.
21
+
22
+ No access token is required for an interactive first publish. Complete the npm
23
+ browser login and any requested two-factor challenge yourself.
24
+
25
+ ## Version and source checks
26
+
27
+ From the Community package directory, check the registry:
28
+
29
+ ```sh
30
+ npm view @blukavantui/community versions --json --registry=https://registry.npmjs.org/
31
+ ```
32
+
33
+ For an unpublished package, a registry 404 is expected. Authentication, permission
34
+ or network errors are different problems. A previously published name/version
35
+ cannot be reused, even after unpublishing. The current local version is `0.4.0`;
36
+ choose the release version after the pending component updates are complete.
37
+
38
+ If you change the version, use `npm version <chosen-version> --no-git-tag-version`,
39
+ then update `edition.json` to match. Check both `package-lock.json` and
40
+ `npm-shrinkwrap.json`; the verifier requires any present lockfile's root version
41
+ to match. Component synchronization preserves the selected package version.
42
+
43
+ Run verification with a supported Node.js LTS release and a current npm CLI:
44
+
45
+ ```sh
46
+ npm ci
47
+ npm run verify:package
48
+ ```
49
+
50
+ This runs type checking, a clean build and the existing tests, packs the package,
51
+ installs that archive into a separate temporary consumer, and verifies all public
52
+ JS/CSS exports, both NodeNext and Bundler TypeScript resolution, the README
53
+ examples, font checksums/licenses and browser bundling. It detects source changes
54
+ while verification is running. Stop concurrent component edits for that run.
55
+
56
+ On success, `release/` contains the archive and `verification.json`, including its
57
+ SHA-256, npm integrity, size and checked source fingerprint. The archive is built
58
+ locally and has not been uploaded. The `prepack` lifecycle also checks/builds/tests
59
+ when running ordinary `npm pack` or publishing the source directory.
60
+
61
+ The package includes editable Community sources and rebuild inputs. Internal
62
+ native verification records and the upstream-only `sync-editions.mjs` script are
63
+ excluded. Third-party notices and font licenses are included. Keep the explicit
64
+ `files` list in `package.json` when adding new build or release inputs.
65
+
66
+ Run browser interaction checks for changed components before release. The package
67
+ verifier checks installability and bundling; it does not replace a full browser,
68
+ accessibility or native OutSystems test suite. Rerun verification after any edits,
69
+ including license or README edits. If verification fails, do not use an archive
70
+ left by an earlier successful run.
71
+
72
+ ## Publish the exact verified archive
73
+
74
+ In the same directory, log in and confirm the active account:
75
+
76
+ ```sh
77
+ npm login --registry=https://registry.npmjs.org/
78
+ npm whoami --registry=https://registry.npmjs.org/
79
+ ```
80
+
81
+ For a verified `0.4.0` release, inspect and then publish this exact archive. Replace
82
+ the filename/version in these commands if you chose a different version:
83
+
84
+ ```sh
85
+ shasum -a 256 release/blukavantui-community-0.4.0.tgz
86
+ npm publish ./release/blukavantui-community-0.4.0.tgz --dry-run --access public --registry=https://registry.npmjs.org/
87
+ npm publish ./release/blukavantui-community-0.4.0.tgz --access public --registry=https://registry.npmjs.org/
88
+ ```
89
+
90
+ Compare the printed SHA-256 with `release/verification.json`. Only the final command
91
+ publishes. Publishing an archive uses its existing contents; it does not rebuild
92
+ pending source changes. Do not publish today's archive after further component
93
+ updates without generating and verifying a new one.
94
+
95
+ To offer a preview while keeping it off the default installation path, choose an
96
+ explicit prerelease version such as `0.4.1-beta.1` and add `--tag next` to publish.
97
+ Users would install `@blukavantui/community@next`. The first stable publication can
98
+ use the default `latest` tag. npm also supports staged publishing with a separate
99
+ maintainer approval step; consult the current npm guide if choosing that workflow.
100
+
101
+ ## After publication
102
+
103
+ - Confirm the version and integrity with `npm view`, then install the exact
104
+ registry version into a fresh application and run its build and browser checks.
105
+ - Remove the pre-publication availability sentence from the README for the next
106
+ release. Keep the website archive option and official-source explanation.
107
+ - Update the website's installation instructions and starter dependency from the
108
+ local archive to the released version, regenerate its lockfile, and verify it.
109
+ - Synchronize the website's license text/summary with `LICENSE.txt` version 1.2
110
+ when releasing the updated downloads. Existing archives retain their original
111
+ terms; do not silently overwrite an already released archive under the same
112
+ version. Use a new version if replacing an existing website release's contents.
113
+ - Keep website downloads, version metadata, release notes and npm contents aligned.
114
+ Forge remains a separate native release.
115
+
116
+ For later automation, configure npm trusted publishing from your CI provider.
117
+ A GitHub Actions workflow can publish using OIDC without a long-lived npm token.
118
+ Do this after the repository and release workflow are settled. Public provenance
119
+ has additional repository visibility requirements; do not assume it is available
120
+ from a private repository.
121
+
122
+ ## Official npm references
123
+
124
+ - [Publish a scoped public package](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/)
125
+ - [Configure two-factor authentication](https://docs.npmjs.com/configuring-two-factor-authentication/)
126
+ - [Create an organization](https://docs.npmjs.com/creating-an-organization/)
127
+ - [Package publication and version immutability](https://docs.npmjs.com/cli/v11/commands/npm-publish/)
128
+ - [Trusted publishing](https://docs.npmjs.com/trusted-publishers/)
129
+ - [npm service rights in your content](https://docs.npmjs.com/policies/open-source-terms/#your-content)