@allxsmith/bestax-bulma 5.67.4 → 5.67.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 (67) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Dropdown.js +24 -5
  4. package/dist/esm/components/Dropdown.js.map +1 -1
  5. package/dist/esm/components/HoverCard.js +4 -1
  6. package/dist/esm/components/HoverCard.js.map +1 -1
  7. package/dist/esm/components/Message.js +8 -1
  8. package/dist/esm/components/Message.js.map +1 -1
  9. package/dist/esm/components/Tabs.js.map +1 -1
  10. package/dist/esm/elements/Notification.js.map +1 -1
  11. package/dist/esm/form/Combobox.js +7 -2
  12. package/dist/esm/form/Combobox.js.map +1 -1
  13. package/dist/esm/form/Control.js.map +1 -1
  14. package/dist/esm/form/DateTimeInputBase.js +23 -3
  15. package/dist/esm/form/DateTimeInputBase.js.map +1 -1
  16. package/dist/esm/form/TimeInputBase.js +6 -2
  17. package/dist/esm/form/TimeInputBase.js.map +1 -1
  18. package/dist/esm/form/_pickerInternals/TimeWheels.js +19 -16
  19. package/dist/esm/form/_pickerInternals/TimeWheels.js.map +1 -1
  20. package/dist/esm/helpers/useFocusTrap.js +84 -10
  21. package/dist/esm/helpers/useFocusTrap.js.map +1 -1
  22. package/dist/esm/helpers/useOtherClasses.js.map +1 -1
  23. package/dist/extras.css +1 -1
  24. package/dist/extras.css.map +1 -1
  25. package/dist/index.cjs +2773 -2641
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/types/components/HoverCard.d.ts +5 -1
  28. package/dist/types/components/Message.d.ts +5 -1
  29. package/dist/types/components/Tabs.d.ts +5 -1
  30. package/dist/types/elements/Notification.d.ts +18 -2
  31. package/dist/types/form/Combobox.d.ts +4 -1
  32. package/dist/types/form/Control.d.ts +18 -4
  33. package/dist/types/form/DateTimeInputBase.d.ts +3 -0
  34. package/dist/types/form/TimeInputBase.d.ts +5 -1
  35. package/dist/types/form/_pickerInternals/TimeWheels.d.ts +6 -0
  36. package/dist/types/helpers/useFocusTrap.d.ts +14 -4
  37. package/dist/types/helpers/useOtherClasses.d.ts +6 -1
  38. package/dist/types-cjs/components/HoverCard.d.ts +5 -1
  39. package/dist/types-cjs/components/Message.d.ts +5 -1
  40. package/dist/types-cjs/components/Tabs.d.ts +5 -1
  41. package/dist/types-cjs/elements/Notification.d.ts +18 -2
  42. package/dist/types-cjs/form/Combobox.d.ts +4 -1
  43. package/dist/types-cjs/form/Control.d.ts +18 -4
  44. package/dist/types-cjs/form/DateTimeInputBase.d.ts +3 -0
  45. package/dist/types-cjs/form/TimeInputBase.d.ts +5 -1
  46. package/dist/types-cjs/form/_pickerInternals/TimeWheels.d.ts +6 -0
  47. package/dist/types-cjs/helpers/useFocusTrap.d.ts +14 -4
  48. package/dist/types-cjs/helpers/useOtherClasses.d.ts +6 -1
  49. package/dist/versions/bestax-no-dark-mode.css +1 -1
  50. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  51. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  52. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  53. package/dist/versions/bestax-no-helpers.css +1 -1
  54. package/dist/versions/bestax-no-helpers.css.map +1 -1
  55. package/dist/versions/bestax-prefixed.css +1 -1
  56. package/dist/versions/bestax-prefixed.css.map +1 -1
  57. package/package.json +1 -1
  58. package/src/scss/CLAUDE.md +4 -1
  59. package/src/scss/_color-classes.scss +27 -0
  60. package/src/scss/_selected-row.scss +2 -10
  61. package/src/scss/components/_hovercard.scss +11 -0
  62. package/src/scss/components/_sidebar.scss +8 -5
  63. package/src/scss/components/_tabs.scss +16 -17
  64. package/src/scss/elements/_notification.scss +30 -1
  65. package/src/scss/form/_combobox.scss +12 -0
  66. package/src/scss/form/_slider.scss +68 -0
  67. package/src/scss/form/_timeinput.scss +7 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allxsmith/bestax-bulma",
3
- "version": "5.67.4",
3
+ "version": "5.67.6",
4
4
  "description": "Component library based on React, Bulma, with Agent Skills and MCP",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.esm.js",
@@ -15,8 +15,11 @@ colors). The `_index.scss` files are the authoritative inventory.
15
15
  - `_variables.scss` — `$extras-*` tokens derived from Bulma's HSL channel vars (`--bulma-primary-h/s/l`)
16
16
  - `_mixins.scss` — shared mixins: `extras-transition`, `extras-focus-outline` (a11y), `extras-sr-only`.
17
17
  It loads no Bulma module, since tests compile it with only this folder on the load path
18
+ - `_color-classes.scss` — `extras-color-classes`, the modifier class of each color in Bulma's
19
+ `$colors`, as a list for a `:not()` that skips an element carrying another color; it reads
20
+ Bulma's `$colors`, which is why it isn't in `_mixins.scss`
18
21
  - `_selected-row.scss` — `extras-selected-table-cell`, the cells Checkbox's and Radio's
19
- selected-row rules share; it reads Bulma's `$colors`, which is why it isn't in `_mixins.scss`
22
+ selected-row rules share, built on `extras-color-classes`
20
23
  - `_input-trigger.scss` — `extras-input-trigger`, a button laid over an input's right edge, which
21
24
  the date and time pickers' launcher and PasswordInput's toggle share; it reads Bulma's class
22
25
  prefix and variables, so it isn't in `_mixins.scss` either
@@ -0,0 +1,27 @@
1
+ // Bestax Extras - Bulma's color classes
2
+ // A function for the partials that name Bulma's color modifiers, so each one
3
+ // reads the same list. It reads Bulma's `$colors`, so it lives here rather
4
+ // than in `_mixins.scss`, which compiles with no Bulma to load.
5
+
6
+ @use 'sass:list';
7
+ @use 'bulma/sass/utilities/initial-variables' as iv;
8
+ @use 'bulma/sass/utilities/derived-variables' as dv;
9
+
10
+ // The modifier class of each color in Bulma's `$colors` map, custom colors
11
+ // included, as a comma-separated list to put in a selector, usually a
12
+ // `:not()`. Bulma's colored elements loop over that map, so a rule can skip
13
+ // an element that carries any of their colors. A name passed in `$except` is
14
+ // left out of the list.
15
+ @function extras-color-classes($except...) {
16
+ $classes: ();
17
+ @each $name, $color in dv.$colors {
18
+ @if not list.index($except, $name) {
19
+ $classes: list.append(
20
+ $classes,
21
+ '.#{iv.$class-prefix}is-#{$name}',
22
+ $separator: comma
23
+ );
24
+ }
25
+ }
26
+ @return $classes;
27
+ }
@@ -3,9 +3,8 @@
3
3
  // name can't drift apart. It reads Bulma's `$colors`, so it lives here rather
4
4
  // than in `_mixins.scss`, which compiles with no Bulma to load.
5
5
 
6
- @use 'sass:list';
7
6
  @use 'bulma/sass/utilities/initial-variables' as iv;
8
- @use 'bulma/sass/utilities/derived-variables' as dv;
7
+ @use 'color-classes' as *;
9
8
 
10
9
  // The cells of a table that sit on Bulma's selected-row fill (`Tr
11
10
  // isSelected`, or a cell with `is-selected`), for a control drawn in the
@@ -23,14 +22,7 @@
23
22
  // is built from, custom colors included. A selected cell is the row's fill
24
23
  // whatever its color, as Bulma paints it.
25
24
  @mixin extras-selected-table-cell {
26
- $colored: ();
27
- @each $name, $color in dv.$colors {
28
- $colored: list.append(
29
- $colored,
30
- '.#{iv.$class-prefix}is-#{$name}',
31
- $separator: comma
32
- );
33
- }
25
+ $colored: extras-color-classes();
34
26
 
35
27
  .#{iv.$class-prefix}table {
36
28
  tr.#{iv.$class-prefix}is-selected:not(#{$colored}) > td:not(#{$colored}),
@@ -84,6 +84,17 @@ $hover-card-animation-duration: 0.15s !default;
84
84
  &.#{iv.$class-prefix}is-top-right {
85
85
  right: 0;
86
86
  }
87
+ // With no `position`, the card lines up with the trigger's inline start,
88
+ // so a trigger at the start of a right-to-left line doesn't push it off the
89
+ // screen. A corner the caller names stays physical. Portaled, the
90
+ // component sets the edge inline instead. `:where()` keeps this at the
91
+ // corner rules' weight, so a theme's own placement still wins.
92
+ &.#{iv.$class-prefix}is-start-aligned:where(
93
+ :not(.#{iv.$class-prefix}is-portal):dir(rtl)
94
+ ) {
95
+ left: auto;
96
+ right: 0;
97
+ }
87
98
 
88
99
  // Portaled: fixed to the viewport at the trigger's edge, which the
89
100
  // component sets inline, so only the gap comes from here.
@@ -306,17 +306,19 @@ $sidebar-static-border-color: cv.getVar("border") !default;
306
306
  }
307
307
  }
308
308
 
309
- // Static variant (inline sidebar, not overlay)
309
+ // Static variant (inline sidebar, not overlay). The border sits between the
310
+ // sidebar and the content: on its end, or its start with `is-right`, so it
311
+ // faces the content on a right-to-left page too.
310
312
  .#{iv.$class-prefix}sidebar.#{iv.$class-prefix}is-static {
311
313
  position: relative;
312
314
  transform: none;
313
315
  box-shadow: none;
314
316
  z-index: auto;
315
- border-right: 1px solid cv.getVar("sidebar-static-border-color");
317
+ border-inline-end: 1px solid cv.getVar("sidebar-static-border-color");
316
318
 
317
319
  &.#{iv.$class-prefix}is-right {
318
- border-right: none;
319
- border-left: 1px solid cv.getVar("sidebar-static-border-color");
320
+ border-inline-end: none;
321
+ border-inline-start: 1px solid cv.getVar("sidebar-static-border-color");
320
322
  }
321
323
  }
322
324
 
@@ -340,8 +342,9 @@ $sidebar-static-border-color: cv.getVar("border") !default;
340
342
  margin: 0;
341
343
  }
342
344
 
345
+ // Out of sight but still in the link, so the link keeps its name.
343
346
  span:not(.#{iv.$class-prefix}icon) {
344
- display: none;
347
+ @include extras-sr-only;
345
348
  }
346
349
  }
347
350
  }
@@ -101,8 +101,9 @@ $tabs-content-padding: 1rem !default;
101
101
  align-items: stretch;
102
102
  border-bottom: none;
103
103
 
104
- // Right border for left-side tabs
105
- border-right: cv.getVar("tabs-vertical-border-width") solid cv.getVar("tabs-vertical-border-color");
104
+ // The edge between the tabs and the panel: their end, which is the
105
+ // left on a right-to-left page, where the panel sits.
106
+ border-inline-end: cv.getVar("tabs-vertical-border-width") solid cv.getVar("tabs-vertical-border-color");
106
107
 
107
108
  > li {
108
109
  width: 100%;
@@ -110,12 +111,12 @@ $tabs-content-padding: 1rem !default;
110
111
  a {
111
112
  justify-content: flex-start;
112
113
  border-bottom: none;
113
- border-right: 2px solid transparent;
114
+ border-inline-end: 2px solid transparent;
114
115
  padding: 0.5em 1em;
115
116
  }
116
117
 
117
118
  &.#{iv.$class-prefix}is-active a {
118
- border-right-color: cv.getVar("link");
119
+ border-inline-end-color: cv.getVar("link");
119
120
  border-bottom-color: transparent;
120
121
  }
121
122
  }
@@ -128,23 +129,24 @@ $tabs-content-padding: 1rem !default;
128
129
  min-width: 0;
129
130
  }
130
131
 
131
- // Right side variant — reverse the flex direction
132
+ // Right side variant — reverse the flex direction, so the tabs sit at the
133
+ // end of the row and the edge moves to their start
132
134
  &.#{iv.$class-prefix}is-right {
133
135
  flex-direction: row-reverse;
134
136
 
135
137
  > .#{iv.$class-prefix}tabs > ul {
136
- border-right: none;
137
- border-left: cv.getVar("tabs-vertical-border-width") solid cv.getVar("tabs-vertical-border-color");
138
+ border-inline-end: none;
139
+ border-inline-start: cv.getVar("tabs-vertical-border-width") solid cv.getVar("tabs-vertical-border-color");
138
140
 
139
141
  > li {
140
142
  a {
141
- border-right: none;
142
- border-left: 2px solid transparent;
143
+ border-inline-end: none;
144
+ border-inline-start: 2px solid transparent;
143
145
  }
144
146
 
145
147
  &.#{iv.$class-prefix}is-active a {
146
- border-left-color: cv.getVar("link");
147
- border-right-color: transparent;
148
+ border-inline-start-color: cv.getVar("link");
149
+ border-inline-end-color: transparent;
148
150
  }
149
151
  }
150
152
  }
@@ -168,21 +170,18 @@ $tabs-content-padding: 1rem !default;
168
170
 
169
171
  > ul {
170
172
  flex-direction: row;
171
- border-right: none;
172
- border-left: none;
173
+ border-inline: none;
173
174
  border-bottom: 1px solid cv.getVar("tabs-vertical-border-color");
174
175
 
175
176
  > li {
176
177
  a {
177
- border-right: none;
178
- border-left: none;
178
+ border-inline: none;
179
179
  border-bottom: 2px solid transparent;
180
180
  }
181
181
 
182
182
  &.#{iv.$class-prefix}is-active a {
183
183
  border-bottom-color: cv.getVar("link");
184
- border-right-color: transparent;
185
- border-left-color: transparent;
184
+ border-inline-color: transparent;
186
185
  }
187
186
  }
188
187
  }
@@ -1,9 +1,10 @@
1
1
  // Notification Styles
2
2
  // Bulma already styles the notification; this keeps its text clear of the
3
- // close button
3
+ // close button, and gives the dark color back its own look
4
4
 
5
5
  @use "bulma/sass/utilities/initial-variables" as iv;
6
6
  @use "bulma/sass/utilities/css-variables" as cv;
7
+ @use "../color-classes" as *;
7
8
 
8
9
  // Bulma pads a notification 1.5em at each end and puts its close button 1rem
9
10
  // in from the end, 1.25rem square, so the button reaches further in than the
@@ -67,3 +68,31 @@ $-delete-sizes: (
67
68
  );
68
69
  }
69
70
  }
71
+
72
+ // Bulma nests a light and a dark variant, `&.is-light` and `&.is-dark`, in
73
+ // each color of its notification. For the dark color the dark variant is
74
+ // `.notification.is-dark.is-dark`, and a class repeated in a selector matches
75
+ // an element that has it once, so every dark notification gets it
76
+ // (jgthms/bulma#3911). It sets a 20% background and reads the text's
77
+ // lightness from `--bulma-dark-dark-invert-l`, which Bulma doesn't define, so
78
+ // the text inherits the color around it and can land one shade off the
79
+ // background. Bulma's buttons skip those variants for white, black, light and
80
+ // dark, and its notification doesn't.
81
+ //
82
+ // This puts back the lightness `.notification.is-dark` sets, the dark
83
+ // color's own. The `:not()` skips a notification that carries another color,
84
+ // so Bulma's dark variant of that color (`is-primary is-dark`) keeps its look,
85
+ // and adds a class's weight, so the rule outranks Bulma's whichever
86
+ // stylesheet loads first. `light` isn't in that list, so `color="dark"
87
+ // isLight` gets the dark look too, the way Bulma gives a dark button no light
88
+ // variant. Once Bulma fixes its loop, this restates Bulma's values and can go.
89
+ .#{iv.$class-prefix}notification.#{iv.$class-prefix}is-dark.#{iv.$class-prefix}is-dark:not(
90
+ #{extras-color-classes("dark", "light")}
91
+ ) {
92
+ @include cv.register-vars(
93
+ (
94
+ "notification-background-l": #{cv.getVar("dark-l")},
95
+ "notification-color-l": #{cv.getVar("dark-invert-l")},
96
+ )
97
+ );
98
+ }
@@ -166,6 +166,18 @@ $combobox-sizes: (
166
166
  right: 0;
167
167
  }
168
168
 
169
+ // With no `position`, the menu lines up with the field's inline start, so
170
+ // a menu wider than a field at the start of a right-to-left line doesn't
171
+ // hang off the screen. A corner the caller names stays physical.
172
+ // Portaled, the component sets the edge inline instead. `:where()` keeps
173
+ // this at the corner rules' weight, so a theme's own placement still wins.
174
+ &.#{iv.$class-prefix}is-start-aligned:where(
175
+ :not(.#{iv.$class-prefix}is-portal):dir(rtl)
176
+ ) {
177
+ left: auto;
178
+ right: 0;
179
+ }
180
+
169
181
  // Portaled: fixed to the viewport at the field's edge, which the component
170
182
  // sets inline with the field's width, so only the gap comes from here.
171
183
  &.#{iv.$class-prefix}is-portal {
@@ -600,7 +600,46 @@ $slider-vertical-height: 200px !default;
600
600
 
601
601
  // High Contrast Mode support
602
602
  @media (forced-colors: active) {
603
+ // The track and the fill are a gradient, which forced colors drops, so a
604
+ // single-thumb slider showed only its thumb. The element that paints them
605
+ // opts out and paints them in the system's colors: the fill in Highlight,
606
+ // the rest of the track in CanvasText, and both in GrayText while
607
+ // disabled. The range slider's track paints the same gradient and had
608
+ // opted out with its own colors, so it takes these too.
609
+ .#{iv.$class-prefix}slider-input,
610
+ .#{iv.$class-prefix}slider.#{iv.$class-prefix}is-range .#{iv.$class-prefix}slider-track {
611
+ forced-color-adjust: none;
612
+ @include cv.register-vars(
613
+ (
614
+ "slider-fill-color": Highlight,
615
+ "slider-track-color": CanvasText,
616
+ )
617
+ );
618
+ }
619
+
620
+ .#{iv.$class-prefix}slider.#{iv.$class-prefix}is-disabled .#{iv.$class-prefix}slider-input,
621
+ .#{iv.$class-prefix}slider.#{iv.$class-prefix}is-disabled.#{iv.$class-prefix}is-range .#{iv.$class-prefix}slider-track {
622
+ @include cv.register-vars(
623
+ (
624
+ "slider-fill-color": GrayText,
625
+ "slider-track-color": GrayText,
626
+ )
627
+ );
628
+ }
629
+
603
630
  .#{iv.$class-prefix}slider-input {
631
+ // The opt-out reaches the thumb too, and forced colors would have
632
+ // dropped its shadows, the focus ring's included. Its border shows focus.
633
+ &::-webkit-slider-thumb,
634
+ &:focus::-webkit-slider-thumb {
635
+ box-shadow: none;
636
+ }
637
+
638
+ &::-moz-range-thumb,
639
+ &:focus::-moz-range-thumb {
640
+ box-shadow: none;
641
+ }
642
+
604
643
  &::-webkit-slider-thumb {
605
644
  background: ButtonText;
606
645
  border-color: ButtonText;
@@ -611,6 +650,17 @@ $slider-vertical-height: 200px !default;
611
650
  border-color: ButtonText;
612
651
  }
613
652
 
653
+ // Hover would paint the border from the fill color, Highlight here, the
654
+ // same as focus. It keeps the rest color, and focus, later, still wins. A
655
+ // disabled thumb's rule below outranks both.
656
+ &::-webkit-slider-thumb:hover {
657
+ border-color: ButtonText;
658
+ }
659
+
660
+ &::-moz-range-thumb:hover {
661
+ border-color: ButtonText;
662
+ }
663
+
614
664
  &:focus::-webkit-slider-thumb {
615
665
  border-color: Highlight;
616
666
  }
@@ -643,6 +693,24 @@ $slider-vertical-height: 200px !default;
643
693
  .#{iv.$class-prefix}slider.#{iv.$class-prefix}is-range .#{iv.$class-prefix}slider-track {
644
694
  forced-color-adjust: none;
645
695
  }
696
+
697
+ // Forced colors turns the value bubble's fill into the page's and paints
698
+ // every side of its arrow, which then draws as a square. An outline, not a
699
+ // border, so the bubble doesn't grow. Only the arrow opts out, so its
700
+ // transparent sides stay transparent and the side that points, whichever
701
+ // way the bubble faces, takes the system's text color.
702
+ .#{iv.$class-prefix}slider-output {
703
+ outline: 1px solid CanvasText;
704
+ }
705
+
706
+ .#{iv.$class-prefix}slider-output::after {
707
+ forced-color-adjust: none;
708
+ @include cv.register-vars(
709
+ (
710
+ "slider-output-background": CanvasText,
711
+ )
712
+ );
713
+ }
646
714
  }
647
715
 
648
716
  // Reduced motion
@@ -142,6 +142,13 @@ $timeinput-footer-padding: 0.5rem 0 0 !default;
142
142
  opacity: 0.55;
143
143
  cursor: not-allowed;
144
144
  }
145
+
146
+ // A read-only wheel turns for nothing, so its items take no pointer: no
147
+ // hover fill and no hand, and a press lands on the wheel, which takes
148
+ // focus as a read-only input does.
149
+ &[aria-readonly='true'] .#{iv.$class-prefix}timeinput-wheel-item {
150
+ pointer-events: none;
151
+ }
145
152
  }
146
153
 
147
154
  .#{iv.$class-prefix}timeinput-wheel-item {