docks_theme_api 1.0.2
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.
- 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;
|