@fusion.dev/helix-core 0.104.1 → 0.106.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.
@@ -25,7 +25,7 @@ export declare class MixinTokensInterface {
25
25
  */
26
26
  maxTags: number;
27
27
  /**
28
- * Whether the count is a control that shows the rest.
28
+ * Whether the count is a button that shows the hidden tokens.
29
29
  *
30
30
  * **Off by default, and that is about focus rather than caution.** The count
31
31
  * becomes a real button when this is set, which is a new stop in the tab
@@ -39,11 +39,12 @@ export declare class MixinTokensInterface {
39
39
  */
40
40
  expandable: boolean;
41
41
  /**
42
- * What the collapsed count is called, since `+3` names nothing.
42
+ * The count button's label, read by screen readers. Its visible text, such
43
+ * as `+3`, does not say what it does.
43
44
  */
44
45
  expandLabel: string;
45
46
  /**
46
- * What the control is called once everything is showing.
47
+ * The button's label, read by screen readers, once every token is showing.
47
48
  *
48
49
  * **The name and not the words on it**, which are a caret: expanded there is
49
50
  * no longer a number to show, and a phrase in its place would translate badly
@@ -11,33 +11,33 @@ export type ViewportControlsPlacement = 'top-start' | 'top-end' | 'bottom-start'
11
11
  * The API a pan-and-zoom surface has, as TypeScript sees it.
12
12
  */
13
13
  export declare class ViewportElement {
14
- /** Which of the controls the surface draws, as a list of what to keep. */
14
+ /** Which controls to show, as a list such as `pan zoom fullscreen`, or `none`. A family adds words of its own. */
15
15
  controls?: string;
16
16
  /** Which corner the controls sit in. */
17
17
  controlsPlacement?: ViewportControlsPlacement;
18
- /** What the control that fills the screen is called. */
18
+ /** The fullscreen button's label. */
19
19
  fullscreenLabel: string;
20
- /** How long the reader may be still before the chrome hides, in milliseconds. */
20
+ /** How long, in milliseconds, before the header and footer hide when the user is inactive. `0` keeps them visible. */
21
21
  idleDelay: number;
22
- /** What the control that pans down is called. */
22
+ /** The pan down button's label. */
23
23
  panDownLabel: string;
24
- /** What the control that pans left is called. */
24
+ /** The pan left button's label. */
25
25
  panLeftLabel: string;
26
- /** What the control that pans right is called. */
26
+ /** The pan right button's label. */
27
27
  panRightLabel: string;
28
- /** How far one press moves the view, as a fraction of what is on screen. */
28
+ /** How far one press pans the view, as a fraction of its size. */
29
29
  panStep: number;
30
- /** What the control that pans up is called. */
30
+ /** The pan up button's label. */
31
31
  panUpLabel: string;
32
- /** What the control that zooms in is called. */
32
+ /** The zoom in button's label. */
33
33
  zoomInLabel: string;
34
- /** What the control that zooms out is called. */
34
+ /** The zoom out button's label. */
35
35
  zoomOutLabel: string;
36
- /** Asks for the view to move, which the consumer answers. */
36
+ /** Pans the view one step in a direction. */
37
37
  pan(to: ViewportWay): void;
38
- /** Asks for the view to zoom, `1` in and `-1` out. */
38
+ /** Zooms the view one step: `1` zooms in and `-1` zooms out. */
39
39
  zoom(by: number): void;
40
- /** Fills the screen with the surface, or comes back. */
40
+ /** Turns fullscreen on or off. */
41
41
  toggleFullscreen(): void;
42
42
  /** Whether the reader has been still long enough to hide the chrome. */
43
43
  protected resting: boolean;
@@ -49,7 +49,7 @@ export declare class ViewportElement {
49
49
  protected readonly fullscreen: FullscreenController;
50
50
  /** The key relay, bound by the family's own frame. */
51
51
  protected handleKeydown: (event: KeyboardEvent) => void;
52
- /** What the group of controls is called, where the page says. */
52
+ /** The name of the group of controls, read by screen readers. */
53
53
  controlsLabel: string | undefined;
54
54
  /** What the group of controls is called where the page does not say, which each family says for itself. */
55
55
  protected get restingControlsLabel(): string;
@@ -63,6 +63,16 @@ export declare class ViewportElement {
63
63
  protected get controlsElement(): Element | null;
64
64
  /** Which controls the surface draws while `controls` is absent. */
65
65
  protected get restingControls(): string;
66
+ /** Whether `controls`, or the resting controls, names a group. */
67
+ protected drawsControls(group: string): boolean;
68
+ /** More buttons for the group of controls, after zoom, for a family that adds its own. */
69
+ protected renderMoreControls(): TemplateResult | typeof nothing;
70
+ /** Answers a key the family adds, and says whether it did. */
71
+ protected handleMoreKeys(event: KeyboardEvent): boolean;
72
+ /** What one pan control is called, for a family that draws its own. */
73
+ protected panLabel(way: ViewportWay): string;
74
+ /** The arrow drawn on one pan control, for a family that draws its own. */
75
+ protected panGlyph(way: ViewportWay): string;
66
76
  }
67
77
  /**
68
78
  * Grafts a pan-and-zoom surface: its controls, its keys, and the way out.
@@ -40,6 +40,10 @@ export const MixinViewport = (Base) => {
40
40
  if (target !== own && !own.matches('[part~="controls"]')) {
41
41
  return;
42
42
  }
43
+ if (this.handleMoreKeys(event)) {
44
+ event.preventDefault();
45
+ return;
46
+ }
43
47
  const along = inlineStep(this, event.key);
44
48
  if (along === 1) {
45
49
  event.preventDefault();
@@ -88,9 +92,15 @@ export const MixinViewport = (Base) => {
88
92
  get restingControls() {
89
93
  return 'pan zoom fullscreen';
90
94
  }
91
- draws(group) {
95
+ drawsControls(group) {
92
96
  return (this.controls ?? this.restingControls).split(/\s+/).includes(group);
93
97
  }
98
+ renderMoreControls() {
99
+ return nothing;
100
+ }
101
+ handleMoreKeys(_event) {
102
+ return false;
103
+ }
94
104
  sideOf(way) {
95
105
  if (way !== 'start' && way !== 'end') {
96
106
  return way;
@@ -101,7 +111,7 @@ export const MixinViewport = (Base) => {
101
111
  const element = this;
102
112
  return !element.hydrating && isRtl(this);
103
113
  }
104
- named(way) {
114
+ panLabel(way) {
105
115
  const side = this.sideOf(way);
106
116
  return side === 'up'
107
117
  ? this.panUpLabel
@@ -111,7 +121,7 @@ export const MixinViewport = (Base) => {
111
121
  ? this.panLeftLabel
112
122
  : this.panRightLabel;
113
123
  }
114
- glyph(way) {
124
+ panGlyph(way) {
115
125
  return { down: '↓', left: '←', right: '→', up: '↑' }[this.sideOf(way)] ?? '';
116
126
  }
117
127
  firstUpdated(changed) {
@@ -126,25 +136,26 @@ export const MixinViewport = (Base) => {
126
136
  return this.renderRoot?.querySelector('[part="controls"]') ?? null;
127
137
  }
128
138
  renderControls() {
129
- const pan = this.draws('pan');
130
- const zoom = this.draws('zoom');
131
- const fullscreen = this.draws('fullscreen');
132
- if (!pan && !zoom && !fullscreen) {
139
+ const pan = this.drawsControls('pan');
140
+ const zoom = this.drawsControls('zoom');
141
+ const fullscreen = this.drawsControls('fullscreen');
142
+ const more = this.renderMoreControls();
143
+ if (!pan && !zoom && !fullscreen && more === nothing) {
133
144
  return nothing;
134
145
  }
135
146
  return html `<div part="controls" role="group" aria-label=${this.controlsLabel ?? this.restingControlsLabel}>
136
147
  ${pan
137
- ? html `<button part="pan-up" aria-label=${this.named('up')} type="button" @click=${() => this.pan('up')}>
138
- ${this.glyph('up')}
148
+ ? html `<button part="pan-up" aria-label=${this.panLabel('up')} type="button" @click=${() => this.pan('up')}>
149
+ ${this.panGlyph('up')}
139
150
  </button>
140
- <button part="pan-start" aria-label=${this.named('start')} type="button" @click=${() => this.pan('start')}>
141
- ${this.glyph('start')}
151
+ <button part="pan-start" aria-label=${this.panLabel('start')} type="button" @click=${() => this.pan('start')}>
152
+ ${this.panGlyph('start')}
142
153
  </button>
143
- <button part="pan-end" aria-label=${this.named('end')} type="button" @click=${() => this.pan('end')}>
144
- ${this.glyph('end')}
154
+ <button part="pan-end" aria-label=${this.panLabel('end')} type="button" @click=${() => this.pan('end')}>
155
+ ${this.panGlyph('end')}
145
156
  </button>
146
- <button part="pan-down" aria-label=${this.named('down')} type="button" @click=${() => this.pan('down')}>
147
- ${this.glyph('down')}
157
+ <button part="pan-down" aria-label=${this.panLabel('down')} type="button" @click=${() => this.pan('down')}>
158
+ ${this.panGlyph('down')}
148
159
  </button>`
149
160
  : nothing}
150
161
  ${zoom
@@ -155,6 +166,7 @@ export const MixinViewport = (Base) => {
155
166
  −
156
167
  </button>`
157
168
  : nothing}
169
+ ${more}
158
170
  ${fullscreen
159
171
  ? html `<button
160
172
  part="fullscreen"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-core",
3
3
  "description": "Helix element primitives: base classes, mixins, decorators, utilities.",
4
- "version": "0.104.1",
4
+ "version": "0.106.0",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -34,11 +34,11 @@
34
34
  "bugs": "https://github.com/project-fusion/fusion/issues",
35
35
  "dependencies": {
36
36
  "@floating-ui/dom": "^1.8.0",
37
- "@fusion.dev/helix-icons": "0.104.1"
37
+ "@fusion.dev/helix-icons": "0.106.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@fusion.dev/helix-cem": "0.104.1",
41
- "@fusion.dev/helix-testing": "0.104.1",
40
+ "@fusion.dev/helix-cem": "0.106.0",
41
+ "@fusion.dev/helix-testing": "0.106.0",
42
42
  "@lit-labs/ssr": "^4.1.0",
43
43
  "lit": "^3.2.1"
44
44
  },