@stackoverflow/stacks 0.74.0 → 1.0.0-beta.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 (89) hide show
  1. package/dist/controllers/index.d.ts +7 -0
  2. package/dist/controllers/s-expandable-control.d.ts +17 -0
  3. package/dist/controllers/s-modal.d.ts +97 -0
  4. package/dist/controllers/s-navigation-tablist.d.ts +36 -0
  5. package/dist/controllers/s-popover.d.ts +155 -0
  6. package/dist/controllers/s-table.d.ts +8 -0
  7. package/dist/controllers/s-tooltip.d.ts +82 -0
  8. package/dist/controllers/s-uploader.d.ts +48 -0
  9. package/dist/css/stacks.css +4633 -2703
  10. package/dist/css/stacks.min.css +1 -1
  11. package/dist/index.d.ts +3 -0
  12. package/dist/js/stacks.js +6026 -5403
  13. package/dist/js/stacks.min.js +1 -1
  14. package/dist/stacks.d.ts +21 -0
  15. package/lib/css/atomic/{_stacks-borders.less → borders.less} +30 -30
  16. package/lib/css/atomic/{_stacks-colors.less → colors.less} +0 -0
  17. package/lib/css/atomic/{_stacks-flex.less → flex.less} +14 -13
  18. package/lib/css/atomic/{_stacks-grid.less → grid.less} +12 -11
  19. package/lib/css/atomic/{_stacks-misc.less → misc.less} +23 -22
  20. package/lib/css/atomic/spacing.less +314 -0
  21. package/lib/css/atomic/{_stacks-typography.less → typography.less} +29 -29
  22. package/lib/css/atomic/width-height.less +194 -0
  23. package/lib/css/base/{_stacks-body.less → body.less} +3 -5
  24. package/lib/css/base/{_stacks-configuration-static.less → configuration-static.less} +3 -1
  25. package/lib/css/base/{_stacks-icons.less → icons.less} +0 -0
  26. package/lib/css/base/{_stacks-internals.less → internals.less} +0 -10
  27. package/lib/css/base/{_stacks-reset-meyer.less → reset-meyer.less} +0 -0
  28. package/lib/css/base/{_stacks-reset-normalize.less → reset-normalize.less} +0 -0
  29. package/lib/css/base/{_stacks-reset.less → reset.less} +2 -2
  30. package/lib/css/components/{_stacks-activity-indicator.less → activity-indicator.less} +9 -9
  31. package/lib/css/components/{_stacks-avatars.less → avatars.less} +40 -40
  32. package/lib/css/components/{_stacks-badges.less → badges.less} +11 -11
  33. package/lib/css/components/{_stacks-banners.less → banners.less} +5 -6
  34. package/lib/css/components/{_stacks-blank-states.less → blank-states.less} +2 -2
  35. package/lib/css/components/{_stacks-breadcrumbs.less → breadcrumbs.less} +7 -7
  36. package/lib/css/components/{_stacks-button-groups.less → button-groups.less} +2 -2
  37. package/lib/css/components/{_stacks-buttons.less → buttons.less} +77 -72
  38. package/lib/css/components/{_stacks-cards.less → cards.less} +2 -2
  39. package/lib/css/components/{_stacks-code-blocks.less → code-blocks.less} +8 -8
  40. package/lib/css/components/{_stacks-collapsible.less → collapsible.less} +0 -0
  41. package/lib/css/components/{_stacks-inputs.less → inputs.less} +41 -41
  42. package/lib/css/components/{_stacks-link-previews.less → link-previews.less} +17 -17
  43. package/lib/css/components/{_stacks-links.less → links.less} +4 -4
  44. package/lib/css/components/{_stacks-menu.less → menu.less} +5 -5
  45. package/lib/css/components/{_stacks-modals.less → modals.less} +20 -20
  46. package/lib/css/components/{_stacks-navigation.less → navigation.less} +12 -12
  47. package/lib/css/components/{_stacks-notices.less → notices.less} +12 -12
  48. package/lib/css/components/{_stacks-page-titles.less → page-titles.less} +9 -9
  49. package/lib/css/components/{_stacks-pagination.less → pagination.less} +8 -8
  50. package/lib/css/components/{_stacks-popovers.less → popovers.less} +17 -17
  51. package/lib/css/components/{_stacks-post-summary.less → post-summary.less} +155 -60
  52. package/lib/css/components/{_stacks-progress-bars.less → progress-bars.less} +29 -30
  53. package/lib/css/components/{_stacks-prose.less → prose.less} +31 -31
  54. package/lib/css/components/{_stacks-spinner.less → spinner.less} +14 -14
  55. package/lib/css/components/{_stacks-tables.less → tables.less} +10 -10
  56. package/lib/css/components/{_stacks-tags.less → tags.less} +33 -41
  57. package/lib/css/components/{_stacks-toggle-switches.less → toggle-switches.less} +5 -5
  58. package/lib/css/components/{_stacks-topbar.less → topbar.less} +27 -40
  59. package/lib/css/components/{_stacks-uploader.less → uploader.less} +18 -18
  60. package/lib/css/components/{_stacks-user-cards.less → user-cards.less} +14 -14
  61. package/lib/css/components/{_stacks-widget-dynamic.less → widget-dynamic.less} +1 -1
  62. package/lib/css/components/{_stacks-widget-static.less → widget-static.less} +39 -38
  63. package/lib/css/exports/{_stacks-constants-colors.less → constants-colors.less} +21 -29
  64. package/lib/css/exports/constants-helpers.less +108 -0
  65. package/lib/css/exports/constants-type.less +153 -0
  66. package/lib/css/exports/{_stacks-exports.less → exports.less} +4 -4
  67. package/lib/css/exports/{_stacks-mixins.less → mixins.less} +18 -1
  68. package/lib/css/stacks-dynamic.less +12 -13
  69. package/lib/css/stacks-static.less +38 -38
  70. package/lib/ts/controllers/index.ts +8 -0
  71. package/lib/ts/controllers/s-expandable-control.ts +163 -164
  72. package/lib/ts/controllers/s-modal.ts +259 -261
  73. package/lib/ts/controllers/s-navigation-tablist.ts +96 -97
  74. package/lib/ts/controllers/s-popover.ts +438 -440
  75. package/lib/ts/controllers/s-table.ts +203 -203
  76. package/lib/ts/controllers/s-tooltip.ts +195 -196
  77. package/lib/ts/controllers/s-uploader.ts +162 -164
  78. package/lib/ts/index.ts +20 -0
  79. package/lib/ts/stacks.ts +73 -68
  80. package/lib/tsconfig.json +8 -6
  81. package/package.json +43 -27
  82. package/dist/css/stacks-flexgrid-shim.min.css +0 -1
  83. package/lib/css/atomic/_stacks-spacing.less +0 -162
  84. package/lib/css/atomic/_stacks-width-height.less +0 -189
  85. package/lib/css/base/_stacks-configuration-dynamic.less +0 -106
  86. package/lib/css/exports/_stacks-constants-helpers.less +0 -139
  87. package/lib/css/exports/_stacks-constants-type.less +0 -91
  88. package/lib/ts/finalize.ts +0 -1
  89. package/lib/ts/stimulus.d.ts +0 -4
@@ -1,190 +1,189 @@
1
- (function(){
2
- // Radio buttons only trigger a change event when they're *checked*, but not when
3
- // they're *unchecked*. Therefore, if we have an active `s-collapsible-control` in
4
- // the document, we listen for change events on *all* radio buttons and find any
5
- // other radio buttons in the same `name` group, triggering a custom event on all
6
- // of them so the controller can re-evaluate.
7
- //
8
- // We're keeping a count of how many of these controllers are connected to the DOM,
9
- // so only have this global listener when we actually need it.
10
- const RADIO_OFF_EVENT = "s-expandable-control:radio-off";
11
-
12
- function globalChangeListener(e: UIEvent) {
13
- const target = e.target;
14
- if (!(target instanceof HTMLInputElement) || target.nodeName !== "INPUT" || target.type !== "radio") {
15
- return;
16
- }
17
- document.querySelectorAll('input[type="radio"][name="' + target.name + '"]')
18
- .forEach(function (other) {
19
- if (other === e.target) {
20
- return;
21
- }
22
- var customEvent;
23
- try {
24
- customEvent = new Event(RADIO_OFF_EVENT);
25
- } catch (ex) {
26
- // Internet Explorer
27
- customEvent = document.createEvent("Event");
28
- customEvent.initEvent(RADIO_OFF_EVENT, true, true);
29
- }
30
- other.dispatchEvent(customEvent);
31
- });
1
+ import * as Stacks from '../stacks';
2
+
3
+ // Radio buttons only trigger a change event when they're *checked*, but not when
4
+ // they're *unchecked*. Therefore, if we have an active `s-collapsible-control` in
5
+ // the document, we listen for change events on *all* radio buttons and find any
6
+ // other radio buttons in the same `name` group, triggering a custom event on all
7
+ // of them so the controller can re-evaluate.
8
+ //
9
+ // We're keeping a count of how many of these controllers are connected to the DOM,
10
+ // so only have this global listener when we actually need it.
11
+ const RADIO_OFF_EVENT = "s-expandable-control:radio-off";
12
+
13
+ function globalChangeListener(e: UIEvent) {
14
+ const target = e.target;
15
+ if (!(target instanceof HTMLInputElement) || target.nodeName !== "INPUT" || target.type !== "radio") {
16
+ return;
32
17
  }
33
-
34
- var refCount = 0;
35
- function globalChangeListenerRequired(required: boolean) {
36
- if (required) {
37
- refCount++;
38
- if (refCount === 1) {
39
- document.body.addEventListener("change", globalChangeListener as EventListener);
18
+ document.querySelectorAll('input[type="radio"][name="' + target.name + '"]')
19
+ .forEach(function (other) {
20
+ if (other === e.target) {
21
+ return;
40
22
  }
41
- } else {
42
- refCount--;
43
- if (refCount === 0) {
44
- document.body.removeEventListener("change", globalChangeListener as EventListener);
23
+ var customEvent;
24
+ try {
25
+ customEvent = new Event(RADIO_OFF_EVENT);
26
+ } catch (ex) {
27
+ // Internet Explorer
28
+ customEvent = document.createEvent("Event");
29
+ customEvent.initEvent(RADIO_OFF_EVENT, true, true);
45
30
  }
31
+ other.dispatchEvent(customEvent);
32
+ });
33
+ }
34
+
35
+ var refCount = 0;
36
+ function globalChangeListenerRequired(required: boolean) {
37
+ if (required) {
38
+ refCount++;
39
+ if (refCount === 1) {
40
+ document.body.addEventListener("change", globalChangeListener as EventListener);
41
+ }
42
+ } else {
43
+ refCount--;
44
+ if (refCount === 0) {
45
+ document.body.removeEventListener("change", globalChangeListener as EventListener);
46
46
  }
47
47
  }
48
+ }
49
+
50
+ export class ExpandableController extends Stacks.StacksController {
51
+ private isCollapsed!: () => boolean;
52
+ private events!: string[];
53
+ private isCheckable!: boolean;
54
+ private isRadio!: boolean;
55
+ private lastKeydownClickTimestamp: number = 0;
56
+
57
+ initialize() {
58
+ if (this.element.nodeName === "INPUT" && ["radio", "checkbox"].indexOf((<HTMLInputElement>this.element).type) >= 0) {
59
+ this.isCollapsed = this._isCollapsedForCheckable;
60
+ this.events = ["change", RADIO_OFF_EVENT];
61
+ this.isCheckable = true;
62
+ this.isRadio = (<HTMLInputElement>this.element).type === "radio";
63
+ } else {
64
+ this.isCollapsed = this._isCollapsedForClickable;
65
+ this.events = ["click", "keydown"];
66
+ }
67
+ this.listener = this.listener.bind(this);
68
+ };
48
69
 
49
- Stacks.application.register("s-expandable-control", class extends Stacks.StacksController {
50
- private isCollapsed!: () => boolean;
51
- private events!: string[];
52
- private isCheckable!: boolean;
53
- private isRadio!: boolean;
54
- private lastKeydownClickTimestamp: number = 0;
55
-
56
- initialize() {
57
- if (this.element.nodeName === "INPUT" && ["radio", "checkbox"].indexOf((<HTMLInputElement>this.element).type) >= 0) {
58
- this.isCollapsed = this._isCollapsedForCheckable;
59
- this.events = ["change", RADIO_OFF_EVENT];
60
- this.isCheckable = true;
61
- this.isRadio = (<HTMLInputElement>this.element).type === "radio";
62
- } else {
63
- this.isCollapsed = this._isCollapsedForClickable;
64
- this.events = ["click", "keydown"];
65
- }
66
- this.listener = this.listener.bind(this);
67
- };
68
70
 
71
+ // for non-checkable elements, the initial source of truth is the collapsed/expanded
72
+ // state of the controlled element (unless the element doesn't exist)
73
+ _isCollapsedForClickable() {
74
+ var cc = this.controlledCollapsibles;
75
+ // the element is considered collapsed if *any* target element is collapsed
76
+ return cc.length > 0 ? !cc.every(element => element.classList.contains("is-expanded")) : this.element.getAttribute("aria-expanded") === "false";
77
+ };
69
78
 
70
- // for non-checkable elements, the initial source of truth is the collapsed/expanded
71
- // state of the controlled element (unless the element doesn't exist)
72
- _isCollapsedForClickable() {
73
- var cc = this.controlledCollapsibles;
74
- // the element is considered collapsed if *any* target element is collapsed
75
- return cc.length > 0 ? !cc.every(element => element.classList.contains("is-expanded")) : this.element.getAttribute("aria-expanded") === "false";
76
- };
79
+ // for checkable elements, the initial source of truth is the checked state
80
+ _isCollapsedForCheckable() {
81
+ return !(<HTMLInputElement>this.element).checked;
82
+ };
77
83
 
78
- // for checkable elements, the initial source of truth is the checked state
79
- _isCollapsedForCheckable() {
80
- return !(<HTMLInputElement>this.element).checked;
81
- };
82
84
 
85
+ get controlledCollapsibles() {
86
+ const attr = this.element.getAttribute("aria-controls");
87
+ if (!attr) {
88
+ throw `[aria-controls="targetId1 ... targetIdN"] attribute required`;
89
+ }
90
+ const result = attr.split(/\s+/g)
91
+ .map(s => document.getElementById(s))
92
+ .filter((e): e is HTMLElement => !!e);
93
+ if (!result.length) {
94
+ throw "couldn't find controls"
95
+ }
96
+ return result;
97
+ };
83
98
 
84
- get controlledCollapsibles() {
85
- const attr = this.element.getAttribute("aria-controls");
86
- if (!attr) {
87
- throw `[aria-controls="targetId1 ... targetIdN"] attribute required`;
99
+ _dispatchShowHideEvent(isShow: boolean) {
100
+ this.triggerEvent(isShow ? "show" : "hide");
101
+ };
102
+
103
+ _toggleClass(doAdd: boolean) {
104
+ if (!this.data.has("toggle-class")) {
105
+ return;
106
+ }
107
+ var cl = this.element.classList;
108
+ var toggleClass = this.data.get("toggle-class");
109
+ if (!toggleClass) {
110
+ throw "couldn't find toggle class"
111
+ }
112
+ toggleClass.split(/\s+/).forEach(function (cls) {
113
+ cl.toggle(cls, !!doAdd);
114
+ });
115
+ };
116
+
117
+ listener(e: Event) {
118
+ var newCollapsed;
119
+ if (this.isCheckable) {
120
+ newCollapsed = !(<HTMLInputElement>this.element).checked;
121
+ } else {
122
+ if (e.type == "keydown" && (e instanceof KeyboardEvent && e.keyCode != 13 && e.keyCode != 32)) {
123
+ return;
88
124
  }
89
- const result = attr.split(/\s+/g)
90
- .map(s => document.getElementById(s))
91
- .filter((e): e is HTMLElement => !!e);
92
- if (!result.length) {
93
- throw "couldn't find controls"
125
+ if (e.target !== e.currentTarget && ["A", "BUTTON"].indexOf((<HTMLElement>e.target).nodeName) >= 0) {
126
+ return;
94
127
  }
95
- return result;
96
- };
97
128
 
98
- _dispatchShowHideEvent(isShow: boolean) {
99
- this.triggerEvent(isShow ? "show" : "hide");
100
- };
129
+ e.preventDefault();
101
130
 
102
- _toggleClass(doAdd: boolean) {
103
- if (!this.data.has("toggle-class")) {
131
+ // Prevent "click" events from toggling the expandable within 300ms of "keydown".
132
+ // e.preventDefault() should have done the same, but https://bugzilla.mozilla.org/show_bug.cgi?id=1487102
133
+ // doesn't guarantee it.
134
+ if (e.type == "keydown") {
135
+ this.lastKeydownClickTimestamp = Date.now();
136
+ } else if (e.type == "click" && Date.now() - this.lastKeydownClickTimestamp < 300) {
104
137
  return;
105
138
  }
106
- var cl = this.element.classList;
107
- var toggleClass = this.data.get("toggle-class");
108
- if (!toggleClass) {
109
- throw "couldn't find toggle class"
110
- }
111
- toggleClass.split(/\s+/).forEach(function (cls) {
112
- cl.toggle(cls, !!doAdd);
113
- });
114
- };
115
-
116
- listener(e: Event) {
117
- var newCollapsed;
118
- if (this.isCheckable) {
119
- newCollapsed = !(<HTMLInputElement>this.element).checked;
120
- } else {
121
- if (e.type == "keydown" && (e instanceof KeyboardEvent && e.keyCode != 13 && e.keyCode != 32)) {
122
- return;
123
- }
124
- if (e.target !== e.currentTarget && ["A", "BUTTON"].indexOf((<HTMLElement>e.target).nodeName) >= 0) {
125
- return;
126
- }
127
-
128
- e.preventDefault();
129
-
130
- // Prevent "click" events from toggling the expandable within 300ms of "keydown".
131
- // e.preventDefault() should have done the same, but https://bugzilla.mozilla.org/show_bug.cgi?id=1487102
132
- // doesn't guarantee it.
133
- if (e.type == "keydown") {
134
- this.lastKeydownClickTimestamp = Date.now();
135
- } else if (e.type == "click" && Date.now() - this.lastKeydownClickTimestamp < 300) {
136
- return;
137
- }
138
- newCollapsed = this.element.getAttribute("aria-expanded") === "true";
139
- if (e.type === "click") {
140
- (<HTMLInputElement>this.element).blur();
141
- }
142
- }
143
- this.element.setAttribute("aria-expanded", newCollapsed ? "false" : "true");
144
- for (let controlledElement of this.controlledCollapsibles) {
145
- controlledElement.classList.toggle("is-expanded", !newCollapsed);
139
+ newCollapsed = this.element.getAttribute("aria-expanded") === "true";
140
+ if (e.type === "click") {
141
+ (<HTMLInputElement>this.element).blur();
146
142
  }
147
- this._dispatchShowHideEvent(!newCollapsed);
148
- this._toggleClass(!newCollapsed);
149
- };
143
+ }
144
+ this.element.setAttribute("aria-expanded", newCollapsed ? "false" : "true");
145
+ for (let controlledElement of this.controlledCollapsibles) {
146
+ controlledElement.classList.toggle("is-expanded", !newCollapsed);
147
+ }
148
+ this._dispatchShowHideEvent(!newCollapsed);
149
+ this._toggleClass(!newCollapsed);
150
+ };
150
151
 
151
- connect() {
152
- this.events.forEach(e => {
153
- this.element.addEventListener(e, this.listener);
154
- }, this);
152
+ connect() {
153
+ this.events.forEach(e => {
154
+ this.element.addEventListener(e, this.listener);
155
+ }, this);
155
156
 
156
- if (this.isRadio) {
157
- globalChangeListenerRequired(true);
158
- }
157
+ if (this.isRadio) {
158
+ globalChangeListenerRequired(true);
159
+ }
159
160
 
160
- // synchronize state -- in all cases, this means setting the correct `aria-expanded`
161
- // attribute; for checkable controls this also means setting the `is-collapsed` class
162
- this.element.setAttribute("aria-expanded", this.isCollapsed() ? "false" : "true");
163
- if (this.isCheckable) {
164
- var cc = this.controlledCollapsibles;
165
- if (cc.length) {
166
- var expected = !this.isCollapsed();
167
- // if any element does not match the expected state, set them all to the expected state
168
- if (cc.some(element => element.classList.contains("is-expanded") !== expected)) {
169
- for (let controlledElement of this.controlledCollapsibles) {
170
- controlledElement.classList.toggle("is-expanded", expected);
171
- }
172
- this._dispatchShowHideEvent(expected);
173
- this._toggleClass(expected);
161
+ // synchronize state -- in all cases, this means setting the correct `aria-expanded`
162
+ // attribute; for checkable controls this also means setting the `is-collapsed` class
163
+ this.element.setAttribute("aria-expanded", this.isCollapsed() ? "false" : "true");
164
+ if (this.isCheckable) {
165
+ var cc = this.controlledCollapsibles;
166
+ if (cc.length) {
167
+ var expected = !this.isCollapsed();
168
+ // if any element does not match the expected state, set them all to the expected state
169
+ if (cc.some(element => element.classList.contains("is-expanded") !== expected)) {
170
+ for (let controlledElement of this.controlledCollapsibles) {
171
+ controlledElement.classList.toggle("is-expanded", expected);
174
172
  }
173
+ this._dispatchShowHideEvent(expected);
174
+ this._toggleClass(expected);
175
175
  }
176
176
  }
177
- };
178
-
179
- disconnect() {
180
- this.events.forEach(e => {
181
- this.element.removeEventListener(e, this.listener);
182
- }, this);
177
+ }
178
+ };
183
179
 
184
- if (this.isRadio) {
185
- globalChangeListenerRequired(false);
186
- }
187
- };
188
- });
180
+ disconnect() {
181
+ this.events.forEach(e => {
182
+ this.element.removeEventListener(e, this.listener);
183
+ }, this);
189
184
 
190
- })();
185
+ if (this.isRadio) {
186
+ globalChangeListenerRequired(false);
187
+ }
188
+ };
189
+ }