docks_theme_api 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.babelrc +4 -0
- data/.editorconfig +8 -0
- data/.eslintrc +115 -0
- data/.gitignore +24 -0
- data/.rubocop.yml +20 -0
- data/.travis.yml +16 -0
- data/Gemfile +4 -0
- data/README.md +5 -0
- data/Rakefile +3 -0
- data/assets/images/icons.svg +63 -0
- data/assets/scripts/coffeescript/pattern_library_helpers.coffee +8 -0
- data/assets/scripts/javascript/pattern_library_helpers.js +11 -0
- data/assets/scripts/pattern_library.js +10380 -0
- data/assets/scripts/pattern_library_demo.js +0 -0
- data/assets/styles/less/pattern-library-helpers.less +103 -0
- data/assets/styles/pattern-library-demo.css +1882 -0
- data/assets/styles/pattern-library.css +1882 -0
- data/assets/styles/sass/pattern-library-helpers.sass +90 -0
- data/assets/styles/scss/pattern-library-helpers.scss +99 -0
- data/assets/styles/stylus/pattern-library-helpers.styl +90 -0
- data/assets/templates/erb/demo.erb +26 -0
- data/assets/templates/erb/layouts/demo.erb +17 -0
- data/assets/templates/erb/layouts/pattern.erb +76 -0
- data/assets/templates/erb/partials/sidebar.erb +124 -0
- data/assets/templates/erb/partials/symbols/class.erb +1 -0
- data/assets/templates/erb/partials/symbols/demo.erb +40 -0
- data/assets/templates/erb/partials/symbols/factory.erb +70 -0
- data/assets/templates/erb/partials/symbols/function.erb +103 -0
- data/assets/templates/erb/partials/symbols/mixin.erb +62 -0
- data/assets/templates/erb/partials/symbols/variable.erb +59 -0
- data/assets/templates/erb/pattern.erb +102 -0
- data/assets/templates/haml/demo.haml +14 -0
- data/assets/templates/haml/layouts/demo.haml +6 -0
- data/assets/templates/haml/layouts/pattern.haml +38 -0
- data/assets/templates/haml/partials/sidebar.haml +68 -0
- data/assets/templates/haml/partials/symbols/class.haml +1 -0
- data/assets/templates/haml/partials/symbols/demo.haml +23 -0
- data/assets/templates/haml/partials/symbols/factory.haml +38 -0
- data/assets/templates/haml/partials/symbols/function.haml +54 -0
- data/assets/templates/haml/partials/symbols/mixin.haml +31 -0
- data/assets/templates/haml/partials/symbols/variable.haml +22 -0
- data/assets/templates/haml/pattern.haml +54 -0
- data/assets/templates/slim/demo.slim +24 -0
- data/assets/templates/slim/layouts/demo.slim +5 -0
- data/assets/templates/slim/layouts/pattern.slim +48 -0
- data/assets/templates/slim/partials/sidebar.slim +112 -0
- data/assets/templates/slim/partials/symbols/class.slim +1 -0
- data/assets/templates/slim/partials/symbols/demo.slim +30 -0
- data/assets/templates/slim/partials/symbols/factory.slim +57 -0
- data/assets/templates/slim/partials/symbols/function.slim +81 -0
- data/assets/templates/slim/partials/symbols/mixin.slim +45 -0
- data/assets/templates/slim/partials/symbols/variable.slim +35 -0
- data/assets/templates/slim/pattern.slim +63 -0
- data/docks_config.rb +32 -0
- data/docks_theme_api.gemspec +37 -0
- data/gulpfile.js +88 -0
- data/karma.conf.js +6 -0
- data/lib/docks_theme_api/components/base_component.rb +99 -0
- data/lib/docks_theme_api/components/code_block_component.rb +10 -0
- data/lib/docks_theme_api/components/popover_component.rb +15 -0
- data/lib/docks_theme_api/components/table_component.rb +34 -0
- data/lib/docks_theme_api/components/tablist_component.rb +11 -0
- data/lib/docks_theme_api/components.rb +21 -0
- data/lib/docks_theme_api/helpers/ui_helper.rb +69 -0
- data/lib/docks_theme_api/theme.rb +21 -0
- data/lib/docks_theme_api.rb +1 -0
- data/package.json +60 -0
- data/source/behaviors/filterable/filterable.coffee +353 -0
- data/source/behaviors/filterable/filterable.js +0 -0
- data/source/behaviors/filterable/filterable.scss +34 -0
- data/source/behaviors/filterable/package.json +3 -0
- data/source/behaviors/index.js +0 -0
- data/source/components/avatar/avatar.erb +20 -0
- data/source/components/avatar/avatar.js +142 -0
- data/source/components/avatar/avatar.scss +200 -0
- data/source/components/avatar/avatar_container.erb +13 -0
- data/source/components/avatar/package.json +3 -0
- data/source/components/avatar/spec/avatar_spec.js +81 -0
- data/source/components/badge/badge.scss +158 -0
- data/source/components/button/button.scss +213 -0
- data/source/components/card/card.scss +32 -0
- data/source/components/code_block/code-block.scss +353 -0
- data/source/components/code_block/code_block.erb +95 -0
- data/source/components/code_block/code_block.js +444 -0
- data/source/components/code_block/package.json +3 -0
- data/source/components/code_block/spec/code_block_spec.js +10 -0
- data/source/components/demo/demo.js +244 -0
- data/source/components/demo/demo.scss +90 -0
- data/source/components/demo/package.json +3 -0
- data/source/components/exploded/exploded.erb +25 -0
- data/source/components/exploded/exploded.js +694 -0
- data/source/components/exploded/exploded.scss +166 -0
- data/source/components/exploded/package.json +3 -0
- data/source/components/field/field.js +24 -0
- data/source/components/field/field.scss +101 -0
- data/source/components/field/package.json +3 -0
- data/source/components/header/header.scss +33 -0
- data/source/components/iframe/iframe.erb +12 -0
- data/source/components/iframe/iframe.js +381 -0
- data/source/components/iframe/package.json +3 -0
- data/source/components/index.js +37 -0
- data/source/components/inline_group/inline-group.scss +14 -0
- data/source/components/internal_link/internal_link.js +49 -0
- data/source/components/internal_link/package.json +3 -0
- data/source/components/list/list.scss +230 -0
- data/source/components/modal/modal.coffee +84 -0
- data/source/components/modal/modal.erb +19 -0
- data/source/components/modal/modal.js +0 -0
- data/source/components/modal/modal.scss +57 -0
- data/source/components/modal/package.json +3 -0
- data/source/components/notice/notice.scss +48 -0
- data/source/components/popover/package.json +3 -0
- data/source/components/popover/popover.coffee +562 -0
- data/source/components/popover/popover.erb +21 -0
- data/source/components/popover/popover.js +0 -0
- data/source/components/popover/popover.scss +139 -0
- data/source/components/range/range.scss +78 -0
- data/source/components/resizable/package.json +3 -0
- data/source/components/resizable/resizable.erb +30 -0
- data/source/components/resizable/resizable.js +250 -0
- data/source/components/resizable/resizable.scss +245 -0
- data/source/components/resizable/size_buttons.js +249 -0
- data/source/components/scroll_container/package.json +3 -0
- data/source/components/scroll_container/scroll-container.scss +4 -0
- data/source/components/scroll_container/scroll_container.js +24 -0
- data/source/components/section/section.scss +99 -0
- data/source/components/select/package.json +3 -0
- data/source/components/select/select.erb +21 -0
- data/source/components/select/select.js +35 -0
- data/source/components/select/select.scss +163 -0
- data/source/components/table/package.json +3 -0
- data/source/components/table/table.erb +16 -0
- data/source/components/table/table.js +351 -0
- data/source/components/table/table.scss +236 -0
- data/source/components/tablist/package.json +3 -0
- data/source/components/tablist/tablist.erb +13 -0
- data/source/components/tablist/tablist.js +246 -0
- data/source/components/tablist/tablist.scss +191 -0
- data/source/components/tablist/tablist_panel.erb +14 -0
- data/source/components/tablist/tablist_tab.erb +20 -0
- data/source/components/toggle/package.json +3 -0
- data/source/components/toggle/toggle.erb +11 -0
- data/source/components/toggle/toggle.js +211 -0
- data/source/components/toggle/toggle_container.erb +30 -0
- data/source/components/vertical_spacer/vertical-spacer.scss +3 -0
- data/source/components/vertical_stack/vertical-stack.scss +19 -0
- data/source/components/xray/package.json +3 -0
- data/source/components/xray/xray.erb +50 -0
- data/source/components/xray/xray.js +123 -0
- data/source/components/xray/xray.scss +79 -0
- data/source/foundation/app/app.js +15 -0
- data/source/foundation/app/package.json +3 -0
- data/source/pattern-library-demo.scss +13 -0
- data/source/pattern-library.scss +13 -0
- data/source/pattern_library.js +8 -0
- data/source/pattern_library_demo.js +8 -0
- data/source/structures/index.js +11 -0
- data/source/structures/sidebar/package.json +3 -0
- data/source/structures/sidebar/sidebar.js +69 -0
- data/source/structures/sidebar/sidebar.scss +79 -0
- data/source/utilities/builder/builder.js +138 -0
- data/source/utilities/builder/package.json +3 -0
- data/source/utilities/client/client.js +7 -0
- data/source/utilities/client/package.json +3 -0
- data/source/utilities/colors/colors.scss +112 -0
- data/source/utilities/defaults/defaults.scss +38 -0
- data/source/utilities/dom_cache/dom_cache.js +24 -0
- data/source/utilities/dom_cache/package.json +3 -0
- data/source/utilities/events/events.js +25 -0
- data/source/utilities/events/package.json +3 -0
- data/source/utilities/font_sizes/font-sizes.scss +85 -0
- data/source/utilities/foundation/a11y.scss +10 -0
- data/source/utilities/foundation/base.scss +29 -0
- data/source/utilities/foundation/icon.scss +114 -0
- data/source/utilities/foundation/layout.scss +67 -0
- data/source/utilities/foundation/page.scss +39 -0
- data/source/utilities/foundation/type.scss +208 -0
- data/source/utilities/functions/functions.scss +127 -0
- data/source/utilities/keycodes/keycodes.js +23 -0
- data/source/utilities/keycodes/package.json +3 -0
- data/source/utilities/markup/markup.js +90 -0
- data/source/utilities/markup/package.json +3 -0
- data/source/utilities/media/media.scss +172 -0
- data/source/utilities/mixins/mixins.scss +89 -0
- data/source/utilities/naming_convention/naming_convention.js +3 -0
- data/source/utilities/naming_convention/package.json +3 -0
- data/source/utilities/numbers/numbers.js +14 -0
- data/source/utilities/numbers/package.json +3 -0
- data/source/utilities/painting/package.json +3 -0
- data/source/utilities/painting/painting.js +7 -0
- data/source/utilities/pattern/package.json +3 -0
- data/source/utilities/pattern/pattern.js +50 -0
- data/source/utilities/query_string/package.json +3 -0
- data/source/utilities/query_string/query_string.js +24 -0
- data/source/utilities/template/package.json +3 -0
- data/source/utilities/template/template.js +10 -0
- data/source/utilities/text_range/package.json +3 -0
- data/source/utilities/text_range/text_range.js +30 -0
- data/source/utilities/ui_events/package.json +3 -0
- data/source/utilities/ui_events/ui_events.js +85 -0
- data/source/utilities/variables/variables.scss +18 -0
- data/source/utilities/z_indexes/z-indexes.scss +88 -0
- data/source/vendor/array_includes.js +28 -0
- data/source/vendor/highlight.js +1142 -0
- data/source/vendor/index.js +1 -0
- data/source/vendor/matrix.js +399 -0
- data/source/vendor/query_string.js +66 -0
- data/spec/assets/.eslintrc +9 -0
- data/spec/assets/spec_fixture.js +33 -0
- data/spec/assets/spec_helper.js +19 -0
- data/spec/lib/components/base_component_spec.rb +156 -0
- data/spec/lib/components_spec.rb +30 -0
- data/spec/lib/helpers/ui_helper_spec.rb +62 -0
- data/spec/lib/theme_spec.rb +25 -0
- data/spec/spec_helper.rb +15 -0
- data/tasks/gulp/.eslintrc +6 -0
- data/tasks/gulp/browser_sync.js +8 -0
- data/tasks/gulp/code_quality/scripts.js +10 -0
- data/tasks/gulp/config/index.js +116 -0
- data/tasks/gulp/minify/scripts.js +13 -0
- data/tasks/gulp/minify/styles.js +13 -0
- data/tasks/gulp/pattern_library/index.js +5 -0
- data/tasks/gulp/pattern_library/scripts.js +10 -0
- data/tasks/gulp/pattern_library/styles.js +10 -0
- data/tasks/gulp/scripts.js +8 -0
- data/tasks/gulp/spec/scripts.js +11 -0
- data/tasks/gulp/styles.js +17 -0
- data/tasks/gulp/utilities/babel/relative_require.js +22 -0
- data/tasks/gulp/utilities/babel/spec_helper.js +20 -0
- data/tasks/gulp/utilities/browserify_bundler.js +22 -0
- data/tasks/gulp/utilities/handle_errors.js +13 -0
- data/tasks/gulp/watch.js +9 -0
- data/tasks/rake/rspec.rake +7 -0
- data/tasks/rake/rubocop.rake +8 -0
- data/tasks/rake/templates.rake +50 -0
- metadata +470 -0
@@ -0,0 +1,245 @@
|
|
1
|
+
// ___ ___ ___ ___ ___
|
2
|
+
// / /\ / /\ / /\ ___ / /\ / /\
|
3
|
+
// / /::\ / /:/_ / /:/_ / /\ / /::| / /:/_
|
4
|
+
// / /:/\:\ / /:/ /\ / /:/ /\ / /:/ / /:/:| / /:/ /\
|
5
|
+
// / /:/~/:/ / /:/ /:/_ / /:/ /::\ /__/::\ / /:/|:|__ / /:/ /:/_
|
6
|
+
// /__/:/ /:/___/__/:/ /:/ /\/__/:/ /:/\:\\__\/\:\__ /__/:/ |:| /\/__/:/ /:/ /\
|
7
|
+
// \ \:\/:::::/\ \:\/:/ /:/\ \:\/:/~/:/ \ \:\/\\__\/ |:|/:/\ \:\/:/ /:/
|
8
|
+
// \ \::/~~~~ \ \::/ /:/ \ \::/ /:/ \__\::/ | |:/:/ \ \::/ /:/
|
9
|
+
// \ \:\ \ \:\/:/ \__\/ /:/ /__/:/ | |::/ \ \:\/:/
|
10
|
+
// \ \:\ \ \::/ /__/:/ \__\/ | |:/ \ \::/
|
11
|
+
// \__\/ \__\/ \__\/ |__|/ \__\/
|
12
|
+
|
13
|
+
//*
|
14
|
+
// @pattern Resizable
|
15
|
+
//
|
16
|
+
// A container that can be resized by dragging on a handle
|
17
|
+
// (`.resizable__handle`) with a contained iframe that shows the actual demo
|
18
|
+
// content. This allows the user to see how the design would actually behave
|
19
|
+
// at different viewport widths, and allows for fixed and absolute positioned
|
20
|
+
// elements to be displayed in a reasonable way.
|
21
|
+
//
|
22
|
+
// The JavaScript portion of this component manages the communication of
|
23
|
+
// height changes from the `iframe` to make sure that the demo is entirely
|
24
|
+
// visible and shows the current width and allows the user to see a small
|
25
|
+
// number of preset widths.
|
26
|
+
//
|
27
|
+
// @since 1.0.0
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
$resizable--min-width: 18rem;
|
32
|
+
$resizable--border: 1px solid ui-color(gray, darker);
|
33
|
+
$resizable--default-transition-timing: 0.3s ease;
|
34
|
+
|
35
|
+
$resizable__handle--width: 1.25rem;
|
36
|
+
$resizable__handle--groove-height: double(default(spacing));
|
37
|
+
$resizable__handle--groove-percentage-width: 0.35;
|
38
|
+
|
39
|
+
$resizable__size-button__icon--size: 1.8rem;
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
//*
|
44
|
+
// The core component of a `Resizable`. This part of the component contains
|
45
|
+
// the handle and `iframe`, and is the part of the component that is actually
|
46
|
+
// resized when dragging the handle/ using the size buttons. The `min-width`
|
47
|
+
// specified here should account for both the `min-width` of the content *and*
|
48
|
+
// the width of the handle (which will be positioned absolutely over the right
|
49
|
+
// side).
|
50
|
+
//
|
51
|
+
// @helper docks_resizable
|
52
|
+
|
53
|
+
.resizable {
|
54
|
+
// position
|
55
|
+
position: relative;
|
56
|
+
|
57
|
+
// box model
|
58
|
+
margin: 0 auto;
|
59
|
+
width: 100%;
|
60
|
+
min-width: ($resizable--min-width + $resizable__handle--width);
|
61
|
+
|
62
|
+
// backdrop
|
63
|
+
@include default(border-radius);
|
64
|
+
|
65
|
+
// type
|
66
|
+
line-height: 0;
|
67
|
+
|
68
|
+
> .card {
|
69
|
+
position: relative;
|
70
|
+
padding-right: $resizable__handle--width;
|
71
|
+
}
|
72
|
+
|
73
|
+
.iframe {
|
74
|
+
width: 100%;
|
75
|
+
min-height: 10rem;
|
76
|
+
transition: height $resizable--default-transition-timing;
|
77
|
+
overflow: hidden;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
//*
|
82
|
+
// Provides a transition that smoothly moves the resizable container from one
|
83
|
+
// width to the next. This is not done by default as dragging the handle would
|
84
|
+
// appear broken.
|
85
|
+
|
86
|
+
.resizable--is-transitioning-width {
|
87
|
+
transition: width $resizable--default-transition-timing;
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
//*
|
93
|
+
// The handle by which to resize the container. Default style gives two small
|
94
|
+
// grooves in the middle of the handle that affords its draggability.
|
95
|
+
|
96
|
+
.resizable__handle {
|
97
|
+
// position
|
98
|
+
position: absolute;
|
99
|
+
top: 0; right: 0;
|
100
|
+
|
101
|
+
// box model
|
102
|
+
width: $resizable__handle--width;
|
103
|
+
height: 100%;
|
104
|
+
|
105
|
+
// backdrop
|
106
|
+
cursor: col-resize;
|
107
|
+
background: ui-color(gray, dark);
|
108
|
+
border-radius: 0 default(border-radius) default(border-radius) 0;
|
109
|
+
|
110
|
+
&:hover,
|
111
|
+
&:focus {
|
112
|
+
outline: none;
|
113
|
+
}
|
114
|
+
|
115
|
+
&:after {
|
116
|
+
$resizable__handle--groove-width: $resizable__handle--groove-percentage-width * $resizable__handle--width;
|
117
|
+
|
118
|
+
content: "";
|
119
|
+
|
120
|
+
// position
|
121
|
+
position: absolute;
|
122
|
+
top: 50%; left: 50%;
|
123
|
+
|
124
|
+
// box model
|
125
|
+
display: block;
|
126
|
+
height: $resizable__handle--groove-height;
|
127
|
+
width: $resizable__handle--groove-width;
|
128
|
+
margin-top: negative(half($resizable__handle--groove-height));
|
129
|
+
margin-left: negative(half($resizable__handle--groove-width));
|
130
|
+
|
131
|
+
// backdrop
|
132
|
+
border-right: $resizable--border;
|
133
|
+
border-left: $resizable--border;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
//*
|
140
|
+
// A container for all of the information and acions available for the
|
141
|
+
// component.
|
142
|
+
|
143
|
+
.resizable__actions {
|
144
|
+
display: flex;
|
145
|
+
justify-content: space-between;
|
146
|
+
align-items: flex-end;
|
147
|
+
margin-bottom: half(default(spacing));
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
//*
|
154
|
+
// A small notice that shows the current width of the (content of the) resizable
|
155
|
+
// module. This indicator slides in when the size changes (through the use of
|
156
|
+
// the `resizable__width-indicator--is-visible` variant).
|
157
|
+
//
|
158
|
+
// The indicator shows the width in both `px` and `em` values which are
|
159
|
+
// contained in the submodules `resizable__width-indicator__px` and
|
160
|
+
// `resizable__width-indicator__em`, respectively.
|
161
|
+
//
|
162
|
+
// @state --is-visible - The indicator is currently being shown.
|
163
|
+
|
164
|
+
.resizable__width-indicator {
|
165
|
+
// type
|
166
|
+
color: color(gray-dark);
|
167
|
+
font: 300 1rem/1 Consolas, monospace;;
|
168
|
+
|
169
|
+
// backdrop
|
170
|
+
opacity: 0.4;
|
171
|
+
transition: opacity $resizable--default-transition-timing;
|
172
|
+
}
|
173
|
+
|
174
|
+
.resizable__width-indicator--is-visible { opacity: 1; }
|
175
|
+
|
176
|
+
|
177
|
+
|
178
|
+
//*
|
179
|
+
// A vertically-oriented set of buttons that resize the resizable module to
|
180
|
+
// predetermined widths. These widths have been set in the Javascript part of
|
181
|
+
// this module.
|
182
|
+
|
183
|
+
.resizable__size-buttons {
|
184
|
+
display: flex;
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
//*
|
190
|
+
// A single button that resizes the module.
|
191
|
+
//
|
192
|
+
// @state --is-active (select)
|
193
|
+
// Indicates that this button has been pressed and that the user has not
|
194
|
+
// subsequently resized the module in some other way.
|
195
|
+
//
|
196
|
+
// @state --is-hidden (none)
|
197
|
+
// Indicates that the button should be hidden because not enough screen space
|
198
|
+
// exists for its resize.
|
199
|
+
//
|
200
|
+
// @variant --small (none) - Resizes to a roughly smartphone-sized width.
|
201
|
+
// @variant --medium (none) - Resizes to a roughly tablet-sized width.
|
202
|
+
// @variant --large (none) - Resizes to a roughly desktop-sized width.
|
203
|
+
|
204
|
+
.resizable__size-button {
|
205
|
+
position: relative;
|
206
|
+
margin-left: half(default(spacing));
|
207
|
+
cursor: pointer;
|
208
|
+
|
209
|
+
opacity: 0.5;
|
210
|
+
transition: opacity $resizable--default-transition-timing;
|
211
|
+
|
212
|
+
> .icon {
|
213
|
+
height: $resizable__size-button__icon--size;
|
214
|
+
width: $resizable__size-button__icon--size;
|
215
|
+
|
216
|
+
@include icon--recolor(gray);
|
217
|
+
transition: fill $resizable--default-transition-timing;
|
218
|
+
}
|
219
|
+
|
220
|
+
&:hover,
|
221
|
+
&:focus,
|
222
|
+
&:active,
|
223
|
+
&.resizable__size-button--is-active {
|
224
|
+
outline: none;
|
225
|
+
}
|
226
|
+
|
227
|
+
&:hover,
|
228
|
+
&:focus {
|
229
|
+
opacity: 0.8;
|
230
|
+
}
|
231
|
+
|
232
|
+
&.resizable__size-button--is-active,
|
233
|
+
&:active {
|
234
|
+
opacity: 1;
|
235
|
+
|
236
|
+
> .icon {
|
237
|
+
fill: color(blue);
|
238
|
+
stroke: color(blue);
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
.resizable__size-button--is-hidden {
|
244
|
+
display: none;
|
245
|
+
}
|
@@ -0,0 +1,249 @@
|
|
1
|
+
import Resizable from "./resizable";
|
2
|
+
import Builder from "~utilities/builder";
|
3
|
+
import Keycodes from "~utilities/keycodes";
|
4
|
+
|
5
|
+
var SizeButtons,
|
6
|
+
SizeRelationships, click_size_button, next_unhidden_size_button,
|
7
|
+
previous_unhidden_size_button, key_on_size_button;
|
8
|
+
|
9
|
+
const classes = {
|
10
|
+
root: "resizable__size-button",
|
11
|
+
container: "resizable__size-buttons"
|
12
|
+
};
|
13
|
+
|
14
|
+
const states = {
|
15
|
+
root: {
|
16
|
+
hidden: "resizable__size-button--is-hidden",
|
17
|
+
active: "resizable__size-button--is-active"
|
18
|
+
}
|
19
|
+
};
|
20
|
+
|
21
|
+
const attrs = {
|
22
|
+
button_size: "data-resizable-size-button-size",
|
23
|
+
size_to: "data-resizable-size-to"
|
24
|
+
};
|
25
|
+
|
26
|
+
SizeRelationships = {
|
27
|
+
SMALL: 320,
|
28
|
+
MEDIUM: 768,
|
29
|
+
LARGE: 960
|
30
|
+
};
|
31
|
+
|
32
|
+
// Attaches media queries for each of the size buttons to conditionally hide/
|
33
|
+
// show them depending on whether or not the size they want to generate is within
|
34
|
+
// the available space.
|
35
|
+
//
|
36
|
+
// @param {HTMLElement} button - The size button. It should have an
|
37
|
+
// `attrs.button_size` attribute, which determines
|
38
|
+
// what size they should make the component.
|
39
|
+
// @param {Number} size_adjustment - The difference in width between the viewport
|
40
|
+
// and the space available to the component.
|
41
|
+
//
|
42
|
+
// @private
|
43
|
+
|
44
|
+
// attach_media_listener_to_size_button = (button, size_adjustment = 0) => {
|
45
|
+
// var size = button.getAttribute(attrs.button_size),
|
46
|
+
// respond_width = SizeRelationships[size.toUpperCase()],
|
47
|
+
// listener, media_query;
|
48
|
+
|
49
|
+
// if(!respond_width) { return; }
|
50
|
+
// button.setAttribute(attrs.size_to, respond_width);
|
51
|
+
|
52
|
+
// listener = (mq) => {
|
53
|
+
// button.classList[mq.matches ? "remove" : "add"](states.size_button.hidden);
|
54
|
+
// };
|
55
|
+
|
56
|
+
// media_query = window.matchMedia(`(min-width: ${respond_width + size_adjustment}px)`);
|
57
|
+
// media_query.addListener(listener);
|
58
|
+
// listener(media_query);
|
59
|
+
// };
|
60
|
+
|
61
|
+
//*
|
62
|
+
// Captures a click even on a size button and sends the appropriate `set_width`
|
63
|
+
// method call to the associated `Resizable` component.
|
64
|
+
//
|
65
|
+
// @param {Object} event - The click event.
|
66
|
+
// @private
|
67
|
+
|
68
|
+
click_size_button = (event) => {
|
69
|
+
var button = $(event.target).closest(`.${classes.root}`);
|
70
|
+
SizeButtons.for(button).active_button = button;
|
71
|
+
};
|
72
|
+
|
73
|
+
//*
|
74
|
+
// Finds the next visible size button after the passed `button`. This is used
|
75
|
+
// for cycling through these buttons with the keyboard. This will cycle through
|
76
|
+
// all buttons in the list, wrapping around to the first buttons if no following
|
77
|
+
// buttons are visible. As a result, this method might return the same `button`
|
78
|
+
// that was passed (if it is the only visible size button).
|
79
|
+
//
|
80
|
+
// @param {HTMLElement} button - The current button (that the user is moving off
|
81
|
+
// of with the keyboard).
|
82
|
+
//
|
83
|
+
// @private
|
84
|
+
// @returns HTMLElement - The next visible size button within the `button`'s set.
|
85
|
+
|
86
|
+
next_unhidden_size_button = (button) => {
|
87
|
+
var sibling = button.nextElementSibling;
|
88
|
+
|
89
|
+
while(sibling) {
|
90
|
+
if(!sibling.classList.contains(states.size_button.hidden)) { return sibling; }
|
91
|
+
sibling = sibling.nextElementSibling;
|
92
|
+
}
|
93
|
+
|
94
|
+
for(sibling of Array.from(button.parentNode.children)) {
|
95
|
+
if(sibling === button) { break; }
|
96
|
+
if(!sibling.classList.contains(states.size_button.hidden)) { return sibling; }
|
97
|
+
}
|
98
|
+
|
99
|
+
return null;
|
100
|
+
};
|
101
|
+
|
102
|
+
//*
|
103
|
+
// Finds the previous visible size button after the passed `button`. This is used
|
104
|
+
// for cycling through these buttons with the keyboard. This will cycle through
|
105
|
+
// all buttons in the list, wrapping around to the last buttons if no previous
|
106
|
+
// buttons are visible. As a result, this method might return the same `button`
|
107
|
+
// that was passed (if it is the only visible size button).
|
108
|
+
//
|
109
|
+
// @param {HTMLElement} button - The current button (that the user is moving off
|
110
|
+
// of with the keyboard).
|
111
|
+
//
|
112
|
+
// @private
|
113
|
+
// @returns HTMLElement - The previous visible size button within the `button`'s
|
114
|
+
// set.
|
115
|
+
|
116
|
+
previous_unhidden_size_button = (button) => {
|
117
|
+
var sibling = button.previousElementSibling;
|
118
|
+
|
119
|
+
while(sibling) {
|
120
|
+
if(!sibling.classList.contains(states.size_button.hidden)) { return sibling; }
|
121
|
+
sibling = sibling.previousElementSibling;
|
122
|
+
}
|
123
|
+
|
124
|
+
for(sibling of Array.from(button.parentNode.children).reverse()) {
|
125
|
+
if(sibling === button) { break; }
|
126
|
+
if(!sibling.classList.contains(states.size_button.hidden)) { return sibling; }
|
127
|
+
}
|
128
|
+
|
129
|
+
return null;
|
130
|
+
};
|
131
|
+
|
132
|
+
//*
|
133
|
+
// Handles key presses on a size button. If the key is enter or space, the
|
134
|
+
// size button will be activated. If the key is an arrow key, this function will
|
135
|
+
// move focus to the correct sibling size button.
|
136
|
+
//
|
137
|
+
// @param {Object} event - The `keypress` event.
|
138
|
+
// @private
|
139
|
+
|
140
|
+
key_on_size_button = (event) => {
|
141
|
+
var button, new_button;
|
142
|
+
|
143
|
+
if(Keycodes.ACTIVATE.includes(event.which)) {
|
144
|
+
event.preventDefault();
|
145
|
+
click_size_button(event);
|
146
|
+
}
|
147
|
+
|
148
|
+
if(Keycodes.ARROWS.includes(event.which)) {
|
149
|
+
event.preventDefault();
|
150
|
+
button = $(event.target).closest(`.${classes.size_button}`)[0];
|
151
|
+
new_button = Keycodes.NEXT.includes(event.which) ?
|
152
|
+
next_unhidden_size_button(button) :
|
153
|
+
previous_unhidden_size_button(button);
|
154
|
+
|
155
|
+
if(new_button) {
|
156
|
+
SizeButtons.for(button).focused_button = new_button;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
};
|
160
|
+
|
161
|
+
//*
|
162
|
+
// @factory
|
163
|
+
|
164
|
+
SizeButtons = (buttons) => {
|
165
|
+
var api,
|
166
|
+
associations, active_button, a11y, activate_button, focus_button,
|
167
|
+
activate_active_button, deactivate_active_button, size, a_button;
|
168
|
+
|
169
|
+
buttons = Array.from(buttons.children);
|
170
|
+
associations = {};
|
171
|
+
for(a_button of buttons) {
|
172
|
+
size = SizeRelationships[a_button.getAttribute(attrs.button_size)];
|
173
|
+
associations[size] = a_button;
|
174
|
+
}
|
175
|
+
|
176
|
+
a11y = {
|
177
|
+
focus(button) {
|
178
|
+
button.setAttribute("tabindex", "0");
|
179
|
+
button.focus();
|
180
|
+
},
|
181
|
+
|
182
|
+
blur(button) {
|
183
|
+
button.setAttribute("tabindex", "-1");
|
184
|
+
},
|
185
|
+
|
186
|
+
select(button) {
|
187
|
+
this.focus(button);
|
188
|
+
button.setAttribute("aria-selected", "true");
|
189
|
+
},
|
190
|
+
|
191
|
+
deselect(button) {
|
192
|
+
this.blur(button);
|
193
|
+
button.setAttribute("aria-selected", "false");
|
194
|
+
}
|
195
|
+
};
|
196
|
+
|
197
|
+
deactivate_active_button = () => {
|
198
|
+
if(!active_button) { return; }
|
199
|
+
|
200
|
+
a11y.deslect(active_button);
|
201
|
+
active_button.classList.remove(states.root.active);
|
202
|
+
};
|
203
|
+
|
204
|
+
activate_button = (button) => {
|
205
|
+
if(!buttons.includes(button) || active_button === button) { return active_button; }
|
206
|
+
|
207
|
+
deactivate_active_button();
|
208
|
+
active_button = button;
|
209
|
+
Resizable.for(button).set_width(parseInt(button.getAttribute(attrs.size_button), 10), { animated: true });
|
210
|
+
activate_active_button();
|
211
|
+
return active_button;
|
212
|
+
};
|
213
|
+
|
214
|
+
focus_button = (button) => {
|
215
|
+
a11y.focus(button);
|
216
|
+
return button;
|
217
|
+
};
|
218
|
+
|
219
|
+
activate_active_button = () => {
|
220
|
+
if(!active_button) { return; }
|
221
|
+
|
222
|
+
a11y.select(active_button);
|
223
|
+
active_button.classList.add(states.root.active);
|
224
|
+
};
|
225
|
+
|
226
|
+
api = {
|
227
|
+
set active_button(button) { return activate_button(button); },
|
228
|
+
get active_button() { return active_button; },
|
229
|
+
set focused_button(button) { return focus_button(button); },
|
230
|
+
|
231
|
+
try_size(new_size) {
|
232
|
+
deactivate_active_button();
|
233
|
+
active_button = associations[new_size];
|
234
|
+
activate_active_button();
|
235
|
+
}
|
236
|
+
};
|
237
|
+
|
238
|
+
return api;
|
239
|
+
};
|
240
|
+
|
241
|
+
SizeButtons.init = () => {
|
242
|
+
Builder.build_and_cache(SizeButtons, { name: classes.container });
|
243
|
+
|
244
|
+
$(document)
|
245
|
+
.on("click", `.${classes.root}`, click_size_button)
|
246
|
+
.on("keydown", `.${classes.root}`, key_on_size_button);
|
247
|
+
};
|
248
|
+
|
249
|
+
export default SizeButtons;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import Builder from "~utilities/builder";
|
2
|
+
|
3
|
+
const classes = {
|
4
|
+
root: "scroll-container"
|
5
|
+
};
|
6
|
+
|
7
|
+
var ScrollContainer;
|
8
|
+
|
9
|
+
ScrollContainer = (node) => {
|
10
|
+
var force_height = (height) => { node.style.minHeight = `${height}px`; };
|
11
|
+
|
12
|
+
return {
|
13
|
+
maintain_current_height() { force_height(node.offsetHeight); },
|
14
|
+
restore_height() { node.style.minHeight = null; },
|
15
|
+
|
16
|
+
scroll_to(contained_node) {
|
17
|
+
node.parentNode.scrollTop = contained_node.getBoundingClientRect().top - node.getBoundingClientRect().top;
|
18
|
+
}
|
19
|
+
};
|
20
|
+
};
|
21
|
+
|
22
|
+
ScrollContainer.init = Builder.initialize_once(ScrollContainer, { name: classes.root, cache: true });
|
23
|
+
|
24
|
+
export default ScrollContainer;
|
@@ -0,0 +1,99 @@
|
|
1
|
+
// ___ ___ ___ ___ ___
|
2
|
+
// / /\ / /\ / /\ ___ ___ / /\ /__/\
|
3
|
+
// / /:/_ / /:/_ / /:/ / /\/ /\ / /::\ \ \:\
|
4
|
+
// / /:/ /\ / /:/ /\ / /:/ / /:/ /:/ / /:/\:\ \ \:\
|
5
|
+
// / /:/ /::\ / /:/ /:/_ / /:/ ___ / /:/__/::\ / /:/ \:\ _____\__\:\
|
6
|
+
// /__/:/ /:/\:\/__/:/ /:/ /\/__/:/ / /\/ /::\__\/\:\__/__/:/ \__\:\/__/::::::::\
|
7
|
+
// \ \:\/:/~/:/\ \:\/:/ /:/\ \:\ / /:/__/:/\:\ \ \:\/\ \:\ / /:/\ \:\~~\~~\/
|
8
|
+
// \ \::/ /:/ \ \::/ /:/ \ \:\ /:/\__\/ \:\ \__\::/\ \:\ /:/ \ \:\ ~~~
|
9
|
+
// \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\/__/:/ \ \:\/:/ \ \:\
|
10
|
+
// /__/:/ \ \::/ \ \::/ \__\/\__\/ \ \::/ \ \:\
|
11
|
+
// \__\/ \__\/ \__\/ \__\/ \__\/
|
12
|
+
|
13
|
+
//*
|
14
|
+
// @pattern Section
|
15
|
+
//
|
16
|
+
// Sections are simply ways of grouping related content and provising
|
17
|
+
// separation between that contained content and "sibling" content.
|
18
|
+
//
|
19
|
+
// Smaller variations are available for more condensed content, like content
|
20
|
+
// inside of a popover.
|
21
|
+
//
|
22
|
+
// @since 1.0.0
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
//*
|
27
|
+
// A container around some content that provides the vertical separation from
|
28
|
+
// other `section`s. This will also remove any top/ bottom padding from the
|
29
|
+
// first/ last child, respectively, to avoid more vertical padding than
|
30
|
+
// necessary.
|
31
|
+
|
32
|
+
.section {
|
33
|
+
margin: double(default(spacing)) 0;
|
34
|
+
padding: default(spacing) 0;
|
35
|
+
|
36
|
+
> *:first-child {
|
37
|
+
&,
|
38
|
+
& > *:first-child {
|
39
|
+
margin-top: 0;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
> *:last-child {
|
44
|
+
&,
|
45
|
+
& > *:last-child {
|
46
|
+
margin-bottom: 0;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
//*
|
52
|
+
// A smaller section with no border separating content. Use this variant for
|
53
|
+
// places where the base amount of vertical padding is excessive (for example,
|
54
|
+
// in popovers or other limited-width containers).
|
55
|
+
|
56
|
+
.section--small {
|
57
|
+
border: none;
|
58
|
+
padding: 0;
|
59
|
+
margin: default(spacing) 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
//*
|
63
|
+
// A section with a light gray background that separates it visually from the
|
64
|
+
// other sections. Use this to differentiate between significantly different
|
65
|
+
// groups of content. It is best to only use this with `section--small` —
|
66
|
+
// regular `section`s already have sufficient separation in most cases.
|
67
|
+
|
68
|
+
.section--subdued {
|
69
|
+
background: color(gray-light);
|
70
|
+
overflow: hidden;
|
71
|
+
|
72
|
+
&.section--small {
|
73
|
+
padding: default(spacing) 0;
|
74
|
+
margin: 0;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
//*
|
81
|
+
// Use this container for when you want a group of sections to have additional
|
82
|
+
// vertical separation from the content around it. The amount of additional
|
83
|
+
// space depends on whether the container contains regular or `--small`
|
84
|
+
// `section`s.
|
85
|
+
//
|
86
|
+
// This container is not necessary — for example, sections can sit on their own
|
87
|
+
// inside a popover.
|
88
|
+
|
89
|
+
.section__container {
|
90
|
+
> .section {
|
91
|
+
&:first-child { margin-top: double(default(spacing)); }
|
92
|
+
&:last-child { margin-bottom: double(default(spacing)); }
|
93
|
+
}
|
94
|
+
|
95
|
+
> .section--small {
|
96
|
+
&:first-child { margin-top: default(spacing); }
|
97
|
+
&:last-child { margin-bottom: default(spacing); }
|
98
|
+
}
|
99
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<%
|
2
|
+
component.configure do |config|
|
3
|
+
config.defaults options: [],
|
4
|
+
name: "select",
|
5
|
+
id: "select",
|
6
|
+
code?: false
|
7
|
+
|
8
|
+
config.classes base: "select",
|
9
|
+
input: "select__input"
|
10
|
+
|
11
|
+
config.conditional_classes if: :code?, base: "select--code"
|
12
|
+
end
|
13
|
+
%>
|
14
|
+
|
15
|
+
<div class="<%= component.classes_for(:base) %>">
|
16
|
+
<select class="<%= component.classes_for(:input) %>" id="<%= component.id %>" name="<%= component.name %>">
|
17
|
+
<% component.options.each do |option| %>
|
18
|
+
<option><%= option %></option>
|
19
|
+
<% end %>
|
20
|
+
</select>
|
21
|
+
</div>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
const classes = {
|
2
|
+
root: "select",
|
3
|
+
input: "select__input"
|
4
|
+
};
|
5
|
+
|
6
|
+
const states = {
|
7
|
+
root: { focused: `${classes.root}--is-focused` }
|
8
|
+
};
|
9
|
+
|
10
|
+
var Select, focus_or_blur_select;
|
11
|
+
|
12
|
+
//*
|
13
|
+
// Translates the `focus`/ `blur` events on the actual `select` node into the
|
14
|
+
// appropriate addition/ removal of the focused state on the base node of the
|
15
|
+
// component. This has to be done because most of the visual styling for the
|
16
|
+
// component is placed on the container, so any adjustments to those styles on
|
17
|
+
// focus require that container to be aware of the state of its contained
|
18
|
+
// `select`.
|
19
|
+
//
|
20
|
+
// @param {Object} event - The `focus`/ `blur` event on the `select`.
|
21
|
+
// @private
|
22
|
+
|
23
|
+
focus_or_blur_select = (event) => {
|
24
|
+
var method = event.type === "focusin" ? "add" : "remove";
|
25
|
+
$(event.target).closest(".#{CLASSES.BASE}")[0].classList[method](states.root.focused);
|
26
|
+
};
|
27
|
+
|
28
|
+
Select = {
|
29
|
+
init() {
|
30
|
+
$(document).on("focus blur", `.${classes.input}`, focus_or_blur_select);
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
export { classes };
|
35
|
+
export default Select;
|