easyfaa 0.90.0 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +213 -7
- data/MIT-LICENSE +3 -1
- data/README.md +64 -20
- data/app/assets/fonts/easy/outfit-latin-ext.woff2 +0 -0
- data/app/assets/fonts/easy/outfit-latin.woff2 +0 -0
- data/app/assets/images/easy/favicon.ico +0 -0
- data/app/assets/images/easy/favicon.svg +11 -0
- data/app/assets/images/easy/sprite.svg +52 -0
- data/app/assets/javascripts/easy/add_rows.js +38 -0
- data/app/assets/javascripts/easy/flyer.js +100 -0
- data/app/assets/javascripts/easy/highlight.js +54 -0
- data/app/assets/javascripts/easy/konami.js +73 -0
- data/app/assets/javascripts/easy/modal.js +49 -0
- data/app/assets/javascripts/easy/pin_code.js +43 -0
- data/app/assets/javascripts/easy/report_sort.js +57 -0
- data/app/assets/javascripts/easy/rotating_placeholder.js +35 -0
- data/app/assets/javascripts/easy/step_foot.js +17 -0
- data/app/assets/javascripts/easy/switches.js +96 -0
- data/app/assets/javascripts/easy/switches_address.js +39 -0
- data/app/assets/javascripts/easy/tabs.js +35 -0
- data/app/assets/javascripts/easy/theme.js +41 -0
- data/app/assets/stylesheets/easy/base.css +42 -0
- data/app/assets/stylesheets/easy/components.css +533 -0
- data/app/assets/stylesheets/easy/layout.css +47 -0
- data/app/assets/stylesheets/easy/tokens.css +11 -0
- data/app/controllers/easyfaa/errors_controller.rb +41 -0
- data/app/helpers/easyfaa/easy_helper.rb +58 -0
- data/app/models/aircraft_avatar.rb +61 -0
- data/app/views/easy/_ad_card.html.erb +16 -0
- data/app/views/easy/_ad_list.html.erb +11 -0
- data/app/views/easy/_flyer.html.erb +10 -0
- data/app/views/easy/_logo.html.erb +15 -0
- data/app/views/easy/_modal.html.erb +17 -0
- data/app/views/easy/_part_tabs.html.erb +24 -0
- data/app/views/easy/_pin_code.html.erb +10 -0
- data/app/views/easy/_report_head.html.erb +28 -0
- data/app/views/easy/mailer/_button.html.erb +10 -0
- data/app/views/easy/mailer/_card.html.erb +23 -0
- data/app/views/easy/mailer/_code.html.erb +28 -0
- data/app/views/easy/mailer/_code.text.erb +19 -0
- data/app/views/easy/mailer/_frame.html.erb +35 -0
- data/app/views/easy/mailer/_text.html.erb +7 -0
- data/app/views/easyfaa/errors/show.html.erb +17 -0
- data/app/views/layouts/easy/site.html.erb +55 -0
- data/app/views/layouts/easyfaa/errors.html.erb +30 -0
- data/config/aircraft_avatars.yml +26 -0
- data/lib/easyfaa/engine.rb +26 -0
- data/lib/easyfaa/version.rb +3 -3
- data/lib/easyfaa.rb +16 -7
- metadata +99 -16
- data/exe/faa +0 -4
- data/lib/easyfaa/cli.rb +0 -65
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ae523d5ac62e5c73325d1f044bbb94c17e9f3f8e4e7e829050a7dfd619395db
|
|
4
|
+
data.tar.gz: 62282f885566e74ef8b61f8b0f5f37afe7cf5c32b0c81515523ba276eaa8f1cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6f950b430699557fe60885cc3e569dbe94c99c8cd158f823ba3b4e2b73717c530183a11d002a41adf77de1dffec0d24d26db4bd04ca3f7d0dfb7a6abaae4596
|
|
7
|
+
data.tar.gz: 32ee475dbf89e8ad9df870c7b5c8715ba312bfab4c64b9be800a20592fc8c59662a2b5e10b928c179e322b6fd7330b46f4f648cad358a351142fa6eb88e9bdb0
|
data/CHANGELOG.md
CHANGED
|
@@ -2,14 +2,220 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
For more information about changelogs, check [Keep a Changelog](http://keepachangelog.com)
|
|
5
|
+
For more information about changelogs, check [Keep a Changelog](http://keepachangelog.com) and
|
|
6
|
+
[Vandamme](http://tech-angels.github.io/vandamme).
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## 1.0.0 - 2026-11-12
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
* [BREAKING] The gem is `easyfaa`, not `wordmark`, and its module is `EasyFAA`: an app's Gemfile
|
|
11
|
+
says `gem 'easyfaa', '~> 1.0'`, names its site with `EasyFAA.site` and routes a page of its own
|
|
12
|
+
to `easyfaa/errors#show`. The easy design system keeps every name an app links
|
|
13
|
+
* The site is at easyfaa.com/design, and design.easyfaa.com redirects there
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
## 0.36.1 - 2026-11-12
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
* A browser without `:focus-visible` rings what has focus, and shows a `has-tip` bubble on hover
|
|
18
|
+
|
|
19
|
+
## 0.36.0 - 2026-11-12
|
|
20
|
+
|
|
21
|
+
* `appliance-card`: a plane card about an appliance, its head gray as a part's and embossed with a radio and a
|
|
22
|
+
battery, a propeller and an oxygen bottle
|
|
23
|
+
|
|
24
|
+
## 0.35.0 - 2026-11-12
|
|
25
|
+
|
|
26
|
+
* [BREAKING] `sky-band` is one size, the one `slim` drew, and `slim` is gone
|
|
27
|
+
|
|
28
|
+
* `add-rows`: things added together, a row at a time from "+ Add …", each with its Remove, and the button that counts
|
|
29
|
+
and saves them, drawn by `easy/add_rows`
|
|
30
|
+
|
|
31
|
+
* `part-card`: a plane card about a part, its head gray and embossed with a wrench and a bolt, a gear and a hex nut
|
|
32
|
+
|
|
33
|
+
## 0.34.1 - 2026-11-12
|
|
34
|
+
|
|
35
|
+
* `step-foot` spans the window under a hairline, whatever holds it, and the `flow-card` it ends has no margin under it
|
|
36
|
+
|
|
37
|
+
## 0.34.0 - 2026-11-12
|
|
38
|
+
|
|
39
|
+
* [BREAKING] A link has no underline but inside a sentence and under the pointer, where its blue deepens; the footer's are underlined
|
|
40
|
+
|
|
41
|
+
* [BREAKING] `pill` is one size, 36 tall, raised, and still under the pointer; `pill soft` is white with dark words, and `small` is gone
|
|
42
|
+
|
|
43
|
+
`--color-primary-strong`, `--shadow-raise`, `--shadow-raise-hover` and `--shadow-sunk` are the tokens they are drawn with.
|
|
44
|
+
|
|
45
|
+
* [BREAKING] `alert-cta` is the main button, large, and `alert-on` a green `removable`; `mini` is a field and a button apart
|
|
46
|
+
|
|
47
|
+
* `removable`, `switch`, `plus-link`, `go-link` and `step-foot` (with `easy/step_foot`), each with its rule in the guide
|
|
48
|
+
|
|
49
|
+
* A field is sunk, the home search's border is gray until typed in, the step numbers are gray, and the recent pages are `removable`
|
|
50
|
+
|
|
51
|
+
## 0.33.4 - 2026-11-12
|
|
52
|
+
|
|
53
|
+
* The email carrying a code names it again in a plain sentence, "Type 123456 in the window you left open.", for Apple Mail to read
|
|
54
|
+
|
|
55
|
+
## 0.33.3 - 2026-11-12
|
|
56
|
+
|
|
57
|
+
* The email carrying a code calls it a "verification code", the words Apple Mail is known to offer a code to its field by
|
|
58
|
+
|
|
59
|
+
## 0.33.2 - 2026-11-12
|
|
60
|
+
|
|
61
|
+
* A search leaves a row's forms out: `easy/switches` matches the words, and `easy/highlight` marks them, outside any `form`
|
|
62
|
+
|
|
63
|
+
## 0.33.1 - 2026-11-12
|
|
64
|
+
|
|
65
|
+
* `mark.search-hit` takes no room of its own: no padding and no bold, so the words around it stay where they were;
|
|
66
|
+
in a flex or grid box, `easy/highlight` keeps the text one piece, so a mark no longer loses the space beside it
|
|
67
|
+
|
|
68
|
+
## 0.33.0 - 2026-11-12
|
|
69
|
+
|
|
70
|
+
* `easy/highlight` marks the words of a search in the rows it leaves, as `mark.search-hit`
|
|
71
|
+
|
|
72
|
+
`easy/report_head` links it with its search, and `easy/switches` calls it at each draw.
|
|
73
|
+
|
|
74
|
+
* [BREAKING] `empty-state` is gone: an empty list and a list left empty by its switches both say so as `none-here`
|
|
75
|
+
|
|
76
|
+
* [BREAKING] `easy/ad_list` takes `size:`: with no card it is the `none:` line alone, and a list left empty by its
|
|
77
|
+
switches says "Nothing matches the filters above."
|
|
78
|
+
|
|
79
|
+
* `easy/tabs` opens the tab whose panel holds what the address names, and brings it into view
|
|
80
|
+
|
|
81
|
+
* `easy/switches` draws again when asked, keeps a row, and hides a group left empty
|
|
82
|
+
|
|
83
|
+
A page that redraws its rows or its switches calls `window.easySwitches()`; a row carrying
|
|
84
|
+
`data-keep` shows whatever its switch says, until a switch is flipped or a word typed; a
|
|
85
|
+
`js-group` hides while no row inside it shows. The switches are read at each draw.
|
|
86
|
+
|
|
87
|
+
* `easy/switches_address` keeps the switches and the search of a `js-switches` box carrying `data-address` in the address
|
|
88
|
+
|
|
89
|
+
## 0.32.0 - 2026-11-12
|
|
90
|
+
|
|
91
|
+
* `easy/part_tabs` draws the parts of an aircraft as tabs over a section each, and `easy/ad_list` a list of ADs
|
|
92
|
+
|
|
93
|
+
Every page that lists ADs part by part hands `easy/part_tabs` its parts (`id:`, `name:`, `icon:`,
|
|
94
|
+
`count:`, `dot:`, `aside:`) and draws each section in its block; `easy/ad_list` is the list of
|
|
95
|
+
cards under its line for none (`none:`, `any:`). The tabs, the switches and the counts read that
|
|
96
|
+
one page.
|
|
97
|
+
|
|
98
|
+
* `easy/report_sort` flips every list `sort_list` names, and `easy/ad_card` carries its number as `data-sort`
|
|
99
|
+
|
|
100
|
+
## 0.31.0 - 2026-11-11
|
|
101
|
+
|
|
102
|
+
* `easy/mailer/frame` draws the page of any email, and `easy/mailer/card`, `text` and `button` what goes on it
|
|
103
|
+
|
|
104
|
+
The frame is the logo, what its block draws and the site; a card is white under a navy head
|
|
105
|
+
(`label:`, `title:`, `note:`), its block rows of `text` and a `button`. `easy_mailer_font` names the
|
|
106
|
+
fonts for a row an app writes itself. The email carrying a code is drawn with them, unchanged.
|
|
107
|
+
|
|
108
|
+
## 0.30.0 - 2026-11-11
|
|
109
|
+
|
|
110
|
+
* `easy/ad_card` draws one AD of an `ad-card-list`, and `easy_level_chip` its level
|
|
111
|
+
|
|
112
|
+
The card takes the AD as plain values (`number:`, `href:`, `subject:`, `title:`, `part:`, `level:`,
|
|
113
|
+
`kind:`, `tie:`, `effective:`, `data:`); rendered as a layout, its block is what the page says
|
|
114
|
+
under the heading: a `why-box`, what replaced it.
|
|
115
|
+
|
|
116
|
+
* [BREAKING] `easy/switches` reads one row of switches: `data-row` is gone, and so is `switches parts`
|
|
117
|
+
|
|
118
|
+
The parts of an aircraft are tabs (`part-tabs`), never switches.
|
|
119
|
+
|
|
120
|
+
## 0.29.0 - 2026-11-11
|
|
121
|
+
|
|
122
|
+
* `easy/switches` recounts a tab as its panel's rows show or hide
|
|
123
|
+
|
|
124
|
+
Inside `js-switches`, a tab of a `js-tabs` whose number carries `js-count` counts the rows left
|
|
125
|
+
in its panel that carry `data-counted`: the ADs in force, not the ones that do not apply.
|
|
126
|
+
|
|
127
|
+
## 0.28.0 - 2026-11-11
|
|
128
|
+
|
|
129
|
+
* `easy/switches` makes the counts of a `switches` row show or hide the rows of their state
|
|
130
|
+
|
|
131
|
+
Inside `js-switches`, anything with a `data-state` is a row; a count with `data-off="true"`
|
|
132
|
+
starts off, words typed in the search narrow the rows too, and a `js-none` line shows when
|
|
133
|
+
nothing is left. `easy/report_head` loads it with its switches. A second row of switches named
|
|
134
|
+
by `data-row` reads that attribute instead, and the rows of switches narrow each other.
|
|
135
|
+
|
|
136
|
+
## 0.27.0 - 2026-11-11
|
|
137
|
+
|
|
138
|
+
* [BREAKING] `field-list` draws no line over each field: the space between them sets them apart
|
|
139
|
+
|
|
140
|
+
* `empty-state`, `steps-bar`'s `is-done` and `show-keys`, `part-tabs-dot` and `level-chip due`, as
|
|
141
|
+
easyAnnual drew them on its own
|
|
142
|
+
|
|
143
|
+
## 0.26.0 - 2026-11-11
|
|
144
|
+
|
|
145
|
+
* [BREAKING] The layout runs the theme itself, with `easy/theme`
|
|
146
|
+
|
|
147
|
+
The header's button and any radio buttons inside `js-theme-choice` (`light`, `dark`,
|
|
148
|
+
`device`) pick the theme with no script of the app's. An app that ran its own on `js-theme`
|
|
149
|
+
removes it, or each click turns the theme twice.
|
|
150
|
+
|
|
151
|
+
* `easy/tabs` shows one panel per tab of a `part-tabs` with `js-tabs`, and keeps the tab in the address
|
|
152
|
+
|
|
153
|
+
## 0.25.0 - 2026-11-11
|
|
154
|
+
|
|
155
|
+
* [BREAKING] `has-tip` is the one tooltip: a bubble over a control that is off, saying why
|
|
156
|
+
|
|
157
|
+
`tooltip`, `tooltip-trigger` and `tooltip-pop` are gone: easyfaa.com, their only user, writes
|
|
158
|
+
on each card what they said. `has-tip` takes its text from `data-tip` and needs no script.
|
|
159
|
+
|
|
160
|
+
* What easyFAA's and easyAnnual's pages both drew on their own is shared: `logo`, `legal`,
|
|
161
|
+
`none-here`, `alert-cta` and `flow-hero` (with `free` and `pulse`)
|
|
162
|
+
|
|
163
|
+
`render layout: "easy/logo"` draws the paper plane and "easy", and the app hands over the
|
|
164
|
+
letters of the rest of its name. The paper plane's `easy/favicon.svg` and `easy/favicon.ico`
|
|
165
|
+
are under `app/assets/images`.
|
|
166
|
+
|
|
167
|
+
* [BREAKING] Rollaway is Ramp, with a mark of its own: a launch ramp, in the slate telex wears
|
|
168
|
+
|
|
169
|
+
`/logo/rollaway.*` and `/favicon/rollaway*` are gone from design.easyfaa.com.
|
|
170
|
+
|
|
171
|
+
* A mark for telex, the app that reads the files mechanics send: a teleprinter, in slate
|
|
172
|
+
|
|
173
|
+
## 0.24.0 - 2026-11-10
|
|
174
|
+
|
|
175
|
+
* [BREAKING] The easy design system is the one front end: the bh layer is gone
|
|
176
|
+
|
|
177
|
+
`/css/easyfaa.css`, `/js/easyfaa.js`, the themes, the IBM Plex and Bootstrap Icons fonts,
|
|
178
|
+
`layouts/easyfaa`, the signup flow and its wall, `easyfaa_head_tags`, `easyfaa_tags`,
|
|
179
|
+
`easyfaa_icons`, `easyfaa_logo`, `Wordmark.app`, `Wordmark.one_time_code`,
|
|
180
|
+
`Wordmark::FormBuilder`, `Wordmark::Message`, `Wordmark::MARKS` and the `easyfaa` npm package
|
|
181
|
+
are gone, and so is the dependency on `bh`. The engine no longer serves `/css`, `/js`,
|
|
182
|
+
`/theme`, `/font`, `/logo`, `/favicon` or `/page`: an app draws with the easy design system
|
|
183
|
+
under `app/assets` and `app/views`, and answers its errors with `Wordmark::ErrorsController`.
|
|
184
|
+
|
|
185
|
+
* design.easyfaa.com is the style guide, in the easy design system, and the marks
|
|
186
|
+
|
|
187
|
+
`rake pages` renders it from the dummy app's `/showcase`, with the site's not-found and down
|
|
188
|
+
pages, which are the apps' own.
|
|
189
|
+
|
|
190
|
+
## 0.23.0 - 2026-11-10
|
|
191
|
+
|
|
192
|
+
* [FEATURE] The easy design system, from `drive`: every easyFAA app's pages are drawn with it
|
|
193
|
+
|
|
194
|
+
`layouts/easy/site`, the stylesheets `easy/tokens`, `easy/base`, `easy/layout` and
|
|
195
|
+
`easy/components`, the Outfit font, the icon sprite, the scripts in `easy/` (modal, pin code,
|
|
196
|
+
flyer, konami, report sort, rotating placeholder), the partials `easy/pin_code`, `easy/modal`,
|
|
197
|
+
`easy/flyer`, `easy/report_head` and `easy/mailer/code`, `easy_icon`, `easy_icon_href`,
|
|
198
|
+
`easy_aircraft_avatar` and `AircraftAvatar`, all by the names drive gave them, and the style
|
|
199
|
+
guide at the dummy app's `/guide`.
|
|
200
|
+
|
|
201
|
+
* [BREAKING] The error pages and `/down.html` are the easy ones, named by `Wordmark.site`
|
|
202
|
+
|
|
203
|
+
A 400, 404, 422 or 500 is answered by `Wordmark::ErrorsController`, and `/down.html` by its
|
|
204
|
+
`down`, naming easyFAA or the site `Wordmark.site` names for the request. `Wordmark::Down`
|
|
205
|
+
is gone, and so is the `wordmark.down` initializer. The site keeps its pages under `/down/`.
|
|
206
|
+
|
|
207
|
+
* [BREAKING] Ruby 3.4 or later
|
|
208
|
+
|
|
209
|
+
## 0.22.0 - 2026-11-10
|
|
210
|
+
|
|
211
|
+
* The front end every easyFAA app shares, from one source tree: the `wordmark` gem, the site at
|
|
212
|
+
design.easyfaa.com and the `easyfaa` npm package
|
|
213
|
+
|
|
214
|
+
A stylesheet and a script layered over bh, the layout and helpers that draw a page's head,
|
|
215
|
+
lockup, down page and one-time code, and a mark for each of easyFAA's apps: tower, hangar,
|
|
216
|
+
lens, rollaway, dataplate, data, refinery, stockroom, blackbox, drive, mirroring and
|
|
217
|
+
wordmark, beside the house's horizon, design's pencil and the cube. Each app's mark is
|
|
218
|
+
drawn at 36 on the 512 grid in a hue of its own from easyfaa.com's tokens, light and dark.
|
|
219
|
+
|
|
220
|
+
`easyfaa_tags` links `/css/easyfaa.css` and `/js/easyfaa.js`, which a browser asks for again
|
|
221
|
+
on every full load and is answered 304 while they stand. A release is one build at the root.
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -1,39 +1,83 @@
|
|
|
1
|
-
#
|
|
1
|
+
# easyFAA design
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
3
|
+
The front end every easyFAA app shares: the easy design system its pages are drawn with (the
|
|
4
|
+
layout, stylesheets, scripts, fonts, icons and partials) and the error pages every app shows.
|
|
5
|
+
Published two ways from `design/` in the brand's repo (`github.com/easyfaa/easyfaa`):
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
| Surface | Where | What it is for |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| Gem | `easyfaa` on RubyGems | A Rails engine: lends an app its views, assets, helpers and error pages |
|
|
10
|
+
| Site | https://easyfaa.com/design | The style guide, every token and component with its markup, and the marks |
|
|
11
|
+
|
|
12
|
+
## How to install
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
# Gemfile
|
|
16
|
+
gem 'easyfaa', '~> 1.0'
|
|
10
17
|
```
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
`~> 1.0` takes every 1.x and stops short of 2.0, the next release that may break an app.
|
|
20
|
+
Rails 8.1 and Ruby 3.4 are the minimum, and the app brings its own asset pipeline (Propshaft).
|
|
14
21
|
|
|
15
|
-
##
|
|
22
|
+
## The easy design system
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
What every easyFAA app's pages are drawn with. The stylesheets, scripts, fonts and icons are
|
|
25
|
+
under `app/assets`, which the host's asset pipeline reads as its own:
|
|
26
|
+
|
|
27
|
+
```erb
|
|
28
|
+
<%# The app's own layout fills the slots, then renders the shared page. %>
|
|
29
|
+
<% content_for :easy_head do %><title>easyFAA</title><% end %>
|
|
30
|
+
<% content_for :site_brand, "easyFAA" %>
|
|
31
|
+
<% content_for :site_nav do %><%= link_to "Sign in", sign_in_path %><% end %>
|
|
32
|
+
<%= javascript_include_tag "easy/modal", "easy/pin_code", defer: true %>
|
|
33
|
+
<%= render template: "layouts/easy/site" %>
|
|
19
34
|
```
|
|
20
35
|
|
|
36
|
+
`layouts/easy/site` links `easy/tokens`, `easy/base`, `easy/layout` and `easy/components` and
|
|
37
|
+
yields `:easy_head`, `:easy_stylesheets`, `:body_class`, `:site_brand_url`, `:site_brand`,
|
|
38
|
+
`:site_nav`, `:sky_band`, `:page_class`, `:site_footer` and `:body_end`. The partials are
|
|
39
|
+
`easy/pin_code`, `easy/modal` (a layout), `easy/flyer`, `easy/report_head` and
|
|
40
|
+
`easy/mailer/code`; the scripts beside them are in `app/assets/javascripts/easy`.
|
|
41
|
+
|
|
42
|
+
`easy_icon "plane"` draws an icon from the sprite every page shares (`easy_icon_href` is its
|
|
43
|
+
address), and `easy_aircraft_avatar AircraftAvatar.for(...)` an aircraft's silhouette until it
|
|
44
|
+
has a picture.
|
|
45
|
+
|
|
46
|
+
The error pages name easyFAA, or the site an app names for the request:
|
|
47
|
+
|
|
21
48
|
```ruby
|
|
22
|
-
|
|
23
|
-
gem 'easyfaa', '~> 0.90'
|
|
49
|
+
EasyFAA.site = ->(request) { ['easyAnnual', 'https://easyannual.com/'] }
|
|
24
50
|
```
|
|
25
51
|
|
|
26
|
-
|
|
52
|
+
The dummy app's `/guide` is the style guide: every token and component, drawn, with its markup.
|
|
53
|
+
## The site
|
|
27
54
|
|
|
28
|
-
|
|
55
|
+
`rake pages` renders the dummy app's `/showcase` (the style guide in the site's own frame, then
|
|
56
|
+
the marks), `/404` and `/down.html` into `public/design/`, every asset they link copied to
|
|
57
|
+
`public/design/assets` under its own name. The marks are the house's own, drawn under `art/` and
|
|
58
|
+
rendered by `build-icons.sh` into `public/design/logo` and `public/design/favicon`; no app shows
|
|
59
|
+
one in public.
|
|
29
60
|
|
|
30
61
|
## Development
|
|
31
62
|
|
|
32
63
|
```bash
|
|
33
|
-
bin/setup
|
|
34
|
-
bundle exec rake
|
|
64
|
+
bin/setup # bundle install
|
|
65
|
+
bundle exec rake # render the site and check it is committed, test at 100% coverage,
|
|
66
|
+
# RuboCop, the file-length ceiling
|
|
67
|
+
./build-icons.sh # after editing a drawing under art/
|
|
68
|
+
cd test/dummy && bin/rails server # /site, /guide and /showcase
|
|
35
69
|
```
|
|
36
70
|
|
|
37
|
-
|
|
71
|
+
A release, in order: `CHANGELOG.md`, the version in `lib/easyfaa/version.rb`, `bundle exec rake`,
|
|
72
|
+
then commit, tag `v<version>`, `gem build` and `gem push`. The site already carries it: it deploys
|
|
73
|
+
from `main`.
|
|
74
|
+
|
|
75
|
+
## Cloudflare
|
|
38
76
|
|
|
39
|
-
|
|
77
|
+
The site is a Worker named `design` that serves `public/` as static assets on the routes
|
|
78
|
+
`easyfaa.com/design` and `easyfaa.com/design/*`, ahead of tower, as `wrangler.jsonc` says; the
|
|
79
|
+
zone's redirect rule sends its old address, `design.easyfaa.com`, there. Workers Builds deploys
|
|
80
|
+
`main` when it changes `design/`, with `npx wrangler deploy` there and no build command: what is
|
|
81
|
+
committed is what is served.
|
|
82
|
+
A path with no file is answered with `design/404.html` and a 404, and every file keeps Cloudflare's
|
|
83
|
+
default of revalidating on every load, so a URL never has to change between versions.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<style>.i{stroke:#15202e}@media (prefers-color-scheme:dark){.i{stroke:#f3f5f8}}</style>
|
|
3
|
+
<g class="i" stroke-width="2.5" stroke-linejoin="round">
|
|
4
|
+
<polygon points="60,8 4,30 25,37" fill="#ffffff"/>
|
|
5
|
+
<polygon points="60,8 25,37 31,57" fill="#cfe0f3"/>
|
|
6
|
+
</g>
|
|
7
|
+
<g stroke="#7a93b3" stroke-width="1.6" stroke-linecap="round">
|
|
8
|
+
<line x1="16" y1="28.5" x2="36" y2="21"/><line x1="21" y1="31.5" x2="44" y2="22.5"/><line x1="27" y1="33" x2="46" y2="25.5"/>
|
|
9
|
+
</g>
|
|
10
|
+
<path d="M10 44 C14 50 18 53 24 55" fill="none" class="i" stroke-width="2" stroke-dasharray="3 3" stroke-linecap="round"/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
2
|
+
<symbol id="i-check" viewBox="0 0 16 16"><circle cx="8" cy="8" r="8" fill="currentColor"/><path d="M4.5 8.2l2.3 2.3 4.7-4.9" fill="none" stroke="#fff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
|
3
|
+
<symbol id="i-applies" viewBox="0 0 16 16"><circle cx="8" cy="8" r="8" fill="currentColor"/><path d="M8 4.2v4.6" stroke="#fff" stroke-width="2" stroke-linecap="round"/><circle cx="8" cy="11.6" r="1.2" fill="#fff"/></symbol>
|
|
4
|
+
<symbol id="i-maybe" viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="2"/><path d="M8 4.2v4.6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><circle cx="8" cy="11.6" r="1.2" fill="currentColor"/></symbol>
|
|
5
|
+
<symbol id="i-none" viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="2"/><path d="M4.8 8h6.4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
|
|
6
|
+
<symbol id="i-alert" viewBox="0 0 16 16"><path d="M8 1.6L14.8 13.8H1.2Z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M8 6v3.6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><circle cx="8" cy="11.6" r="1" fill="currentColor"/></symbol>
|
|
7
|
+
<symbol id="i-superseded" viewBox="0 0 16 16"><path d="M3.5 1.75h5.75l3.25 3.25v9.25h-9z" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M9.25 1.75v3.25h3.25" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M1.5 14.5L14.5 1.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></symbol>
|
|
8
|
+
<symbol id="i-engine" viewBox="0 0 24 24"><path fill="currentColor" d="M7 4v2h3v2H7l-2 2v3H3v-3H1v8h2v-3h2v3h3l2 2h8v-4h2v3h3V9h-3v3h-2V8h-6V6h3V4z"/></symbol>
|
|
9
|
+
<symbol id="i-propeller" viewBox="0 0 16 16"><g fill="currentColor"><path d="M8 7.4C5.4 6 5.3 2.1 8 .5c2.7 1.6 2.6 5.5 0 6.9z"/><path d="M8 7.4C5.4 6 5.3 2.1 8 .5c2.7 1.6 2.6 5.5 0 6.9z" transform="rotate(120 8 8)"/><path d="M8 7.4C5.4 6 5.3 2.1 8 .5c2.7 1.6 2.6 5.5 0 6.9z" transform="rotate(240 8 8)"/><circle cx="8" cy="8" r="2.1"/></g></symbol>
|
|
10
|
+
<symbol id="i-appliance" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M13.07 6.45L15.31 6.84L15.31 9.16L13.07 9.55L12.68 10.49L13.99 12.35L12.35 13.99L10.49 12.68L9.55 13.07L9.16 15.31L6.84 15.31L6.45 13.07L5.51 12.68L3.65 13.99L2.01 12.35L3.32 10.49L2.93 9.55L0.69 9.16L0.69 6.84L2.93 6.45L3.32 5.51L2.01 3.65L3.65 2.01L5.51 3.32L6.45 2.93L6.84 0.69L9.16 0.69L9.55 2.93L10.49 3.32L12.35 2.01L13.99 3.65L12.68 5.51Z M8 5.6a2.4 2.4 0 1 0 0 4.8a2.4 2.4 0 1 0 0-4.8Z"/></symbol>
|
|
11
|
+
<symbol id="i-calendar" viewBox="0 0 16 16"><rect x="2" y="3" width="12" height="11" rx="2" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M2 6.5h12M5 1.5v3M11 1.5v3" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></symbol>
|
|
12
|
+
<symbol id="i-newest" viewBox="0 0 16 16"><path d="M4 2.5v10M1.5 10l2.5 2.5L6.5 10M9 4h5.5M9 7.5h4M9 11h2.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
|
13
|
+
<symbol id="i-oldest" viewBox="0 0 16 16"><path d="M4 13.5v-10M1.5 6L4 3.5 6.5 6M9 4h2.5M9 7.5h4M9 11h5.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
|
14
|
+
<symbol id="i-search" viewBox="0 0 24 24"><circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2.4"/><path d="M15.5 15.5l5 5" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></symbol>
|
|
15
|
+
<symbol id="i-bookmark" viewBox="0 0 16 16"><path d="M4 1.5h8a.5.5 0 0 1 .5.5v12.3L8 11.2l-4.5 3.1V2a.5.5 0 0 1 .5-.5z" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></symbol>
|
|
16
|
+
<symbol id="i-share" viewBox="0 0 16 16"><circle cx="12" cy="3.5" r="2" fill="none" stroke="currentColor" stroke-width="1.5"/><circle cx="4" cy="8" r="2" fill="none" stroke="currentColor" stroke-width="1.5"/><circle cx="12" cy="12.5" r="2" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M5.8 7l4.4-2.5M5.8 9l4.4 2.5" stroke="currentColor" stroke-width="1.5"/></symbol>
|
|
17
|
+
<symbol id="i-link" viewBox="0 0 16 16"><path d="M6.6 9.4l2.8-2.8M7 4.6l1.2-1.2a2.8 2.8 0 0 1 4 4L11 8.6M9 11.4l-1.2 1.2a2.8 2.8 0 0 1-4-4L5 7.4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></symbol>
|
|
18
|
+
<symbol id="i-out" viewBox="0 0 16 16"><path d="M9 2.5h4.5V7M13.5 2.5L7.5 8.5M11.5 9.5v3a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h3" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
|
19
|
+
<symbol id="i-sun" viewBox="0 0 16 16"><circle cx="8" cy="8" r="3.2" fill="currentColor"/><path d="M8 .8v2M8 13.2v2M.8 8h2M13.2 8h2M2.9 2.9l1.4 1.4M11.7 11.7l1.4 1.4M2.9 13.1l1.4-1.4M11.7 4.3l1.4-1.4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></symbol>
|
|
20
|
+
<symbol id="i-moon" viewBox="0 0 16 16"><path d="M13.5 10.2A6 6 0 0 1 5.8 2.5a6 6 0 1 0 7.7 7.7z" fill="currentColor"/></symbol>
|
|
21
|
+
<symbol id="i-monitor" viewBox="0 0 16 16"><rect x="1.2" y="2" width="13.6" height="9" rx="1.4" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M5.5 14.2h5M8 11v3.2" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></symbol>
|
|
22
|
+
<symbol id="i-plane" viewBox="0 0 24 24"><path d="M21 15.5v-2l-8-5V3.2a1.5 1.5 0 0 0-3 0V8.5l-8 5v2l8-2.5v5.2l-2 1.5V21l3.5-1 3.5 1v-1.3l-2-1.5V13z" fill="currentColor"/></symbol>
|
|
23
|
+
<symbol id="i-small-plane" viewBox="0 0 24 24"><path fill="currentColor" d="M8.2 1.1h7.6v1.1H8.2zM12 2.2c1.1 0 1.7 1.1 1.7 2.7v3.2h8.1c.5 0 .9.4.9.9v1.7c0 .5-.4.9-.9.9h-8.1l-.8 7.1h2.9c.5 0 .8.3.8.8v1c0 .5-.3.8-.8.8H8.2c-.5 0-.8-.3-.8-.8v-1c0-.5.3-.8.8-.8h2.9l-.8-7.1H2.2c-.5 0-.9-.4-.9-.9V9c0-.5.4-.9.9-.9h8.1V4.9c0-1.6.6-2.7 1.7-2.7z"/></symbol>
|
|
24
|
+
<symbol id="i-twin-plane" viewBox="0 0 24 24"><path fill="currentColor" d="M12 1.8c.9 0 1.5 1 1.5 2.6v13.4l-.5 2.8h-2l-.5-2.8V4.4c0-1.6.6-2.6 1.5-2.6zM1.3 10.2h21.4c.5 0 .8.3.8.8v1.4c0 .5-.3.8-.8.8H1.3c-.5 0-.8-.3-.8-.8V11c0-.5.3-.8.8-.8zM7 6.2c.7 0 1.2.5 1.2 1.2v7H5.8v-7c0-.7.5-1.2 1.2-1.2zM17 6.2c.7 0 1.2.5 1.2 1.2v7h-2.4v-7c0-.7.5-1.2 1.2-1.2zM4.8 5h4.4v1H4.8zM14.8 5h4.4v1h-4.4zM8.2 19.2h7.6c.3 0 .5.2.5.5v1c0 .3-.2.5-.5.5H8.2c-.3 0-.5-.2-.5-.5v-1c0-.3.2-.5.5-.5z"/></symbol>
|
|
25
|
+
<symbol id="s-x" viewBox="0 0 24 24"><path fill="currentColor" d="M17.8 3h3.1l-6.8 7.8L22 21h-6.2l-4.9-6.4L5.3 21H2.2l7.3-8.3L1.9 3h6.3l4.4 5.9zm-1.1 16.2h1.7L7.4 4.7H5.6z"/></symbol>
|
|
26
|
+
<symbol id="s-fb" viewBox="0 0 24 24"><path fill="currentColor" d="M13.6 22v-8.2h2.8l.4-3.3h-3.2V8.4c0-.9.3-1.6 1.6-1.6h1.7V3.9c-.3 0-1.3-.1-2.5-.1-2.5 0-4.2 1.5-4.2 4.3v2.4H7.4v3.3h2.8V22z"/></symbol>
|
|
27
|
+
<symbol id="s-li" viewBox="0 0 24 24"><path fill="currentColor" d="M3.6 8.6h3.7V20.5H3.6zM5.45 2.8a2.15 2.15 0 110 4.3 2.15 2.15 0 010-4.3zM9.6 8.6h3.5v1.6h.1c.5-.9 1.7-1.9 3.5-1.9 3.8 0 4.5 2.5 4.5 5.7v6.5h-3.7v-5.8c0-1.4 0-3.2-1.9-3.2s-2.3 1.5-2.3 3.1v5.9H9.6z"/></symbol>
|
|
28
|
+
<symbol id="s-rd" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M19.7 5.3a1.6 1.6 0 11-1.5 2l-3.3-.7-1 4.4c2.2.1 4.2.8 5.6 1.9a2.2 2.2 0 113 3 4.3 4.3 0 010 .6c0 3.4-4 6.1-8.5 6.1S5.5 19.9 5.5 16.5v-.6a2.2 2.2 0 113-3c1.4-1 3.3-1.7 5.4-1.8l1.2-5.3 4 .9a1.6 1.6 0 01.6-1.4zM9.3 14.2a1.4 1.4 0 100 2.8 1.4 1.4 0 000-2.8zm5.4 0a1.4 1.4 0 100 2.8 1.4 1.4 0 000-2.8zm-5.2 4.3a.5.5 0 00-.3.9c.9.7 2 1 2.8 1s1.9-.3 2.8-1a.5.5 0 10-.6-.8c-.6.5-1.4.8-2.2.8s-1.6-.3-2.2-.8a.5.5 0 00-.3-.1z"/></symbol>
|
|
29
|
+
<symbol id="s-wa" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2a10 10 0 00-8.6 15.1L2 22l5-1.3A10 10 0 1012 2zm0 1.8a8.2 8.2 0 11-4.2 15.3l-.3-.2-3 .8.8-2.9-.2-.3A8.2 8.2 0 0112 3.8zM8.6 7.2c-.2 0-.5 0-.8.3-.3.3-1 1-1 2.5s1.1 2.9 1.2 3.1c.2.2 2.1 3.3 5.2 4.5 2.6 1 3.1.8 3.7.8.6-.1 1.8-.7 2-1.5.3-.7.3-1.3.2-1.5l-.6-.4-2-1c-.3-.1-.5-.1-.7.1l-.9 1.2c-.2.2-.3.2-.6.1-.3-.2-1.3-.5-2.4-1.5-.9-.8-1.5-1.8-1.7-2.1-.2-.3 0-.5.1-.6l.5-.6.3-.5v-.5l-.9-2.3c-.2-.6-.5-.5-.7-.5z"/></symbol>
|
|
30
|
+
<symbol id="s-em" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" d="M3 5.5h18v13H3zM3.5 6l8.5 7 8.5-7"/></symbol>
|
|
31
|
+
<!-- Aircraft avatars (a-): side views, nose right, drones from above; holes take the avatar background. -->
|
|
32
|
+
<symbol id="a-high-wing" viewBox="1 1 46 46" fill="currentColor"><path d="M43.5 24.2C43.5 22 41.5 20.8 39 20.6L35 18.6H24.5L9 21.4H5V24.2L24 27.2H38.5C41.5 27.2 43.5 26.4 43.5 24.2Z"/><path d="M34.2 19.3L37.6 21H33.8V19.3ZM25.2 19.3H32.8V21H25.2Z" style="fill:var(--avatar-bg,#fff)"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="21.5" y="16.6" width="13.0" height="2.0" rx="0.8"/><line x1="31" y1="18.4" x2="27" y2="26.4" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><line x1="38.5" y1="27" x2="38.5" y2="32.2" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="38.5" cy="33.6" r="2"/><line x1="28" y1="27" x2="29" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="29" cy="33.6" r="2.3"/></symbol>
|
|
33
|
+
<symbol id="a-high-wing-tailwheel" viewBox="1 1 46 46" fill="currentColor"><g transform="rotate(-8 24 28)"><path d="M43.5 24.2C43.5 22 41.5 20.8 39 20.6L35 18.6H24.5L9 21.4H5V24.2L24 27.2H38.5C41.5 27.2 43.5 26.4 43.5 24.2Z"/><path d="M34.2 19.3L37.6 21H33.8V19.3ZM25.2 19.3H32.8V21H25.2Z" style="fill:var(--avatar-bg,#fff)"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="21.5" y="16.6" width="13.0" height="2.0" rx="0.8"/><line x1="31" y1="18.4" x2="27" y2="26.4" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><line x1="32.5" y1="27" x2="34" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="34" cy="33.6" r="2.3"/><line x1="7.5" y1="23.8" x2="7" y2="25.6" stroke="currentColor" stroke-width="0.9" stroke-linecap="round"/><circle cx="7" cy="26.2" r="1.1"/></g></symbol>
|
|
34
|
+
<symbol id="a-low-wing" viewBox="1 1 46 46" fill="currentColor"><path d="M43.5 24.2C43.5 22 41.5 20.8 39 20.6L35 18.6H24.5L9 21.4H5V24.2L24 27.2H38.5C41.5 27.2 43.5 26.4 43.5 24.2Z"/><path d="M34.2 19.3L37.6 21H33.8V19.3ZM25.2 19.3H32.8V21H25.2Z" style="fill:var(--avatar-bg,#fff)"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="20" y="26.4" width="14.5" height="2.0" rx="0.8"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><line x1="38.5" y1="27" x2="38.5" y2="32.2" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="38.5" cy="33.6" r="2"/><line x1="28" y1="27" x2="29" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="29" cy="33.6" r="2.3"/></symbol>
|
|
35
|
+
<symbol id="a-low-wing-retractable" viewBox="1 1 46 46" fill="currentColor"><path d="M43.5 24.2C43.5 22 41.5 20.8 39 20.6L35 18.6H24.5L9 21.4H5V24.2L24 27.2H38.5C41.5 27.2 43.5 26.4 43.5 24.2Z"/><path d="M34.2 19.3L37.6 21H33.8V19.3ZM25.2 19.3H32.8V21H25.2Z" style="fill:var(--avatar-bg,#fff)"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="20" y="26.4" width="14.5" height="2.0" rx="0.8"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/></symbol>
|
|
36
|
+
<symbol id="a-low-wing-tailwheel" viewBox="1 1 46 46" fill="currentColor"><g transform="rotate(-8 24 28)"><path d="M43.5 24.2C43.5 22 41.5 21 39 21H31L28 18.4C26.5 17.6 23.5 17.6 22 18.6L19.5 21H9L5 21.4V24L24 27H38.5C41.5 27 43.5 26.4 43.5 24.2Z"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="20" y="26.4" width="14.5" height="2.0" rx="0.8"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><line x1="32.5" y1="27" x2="34" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="34" cy="33.6" r="2.3"/><line x1="7.5" y1="23.8" x2="7" y2="25.6" stroke="currentColor" stroke-width="0.9" stroke-linecap="round"/><circle cx="7" cy="26.2" r="1.1"/></g></symbol>
|
|
37
|
+
<symbol id="a-biplane" viewBox="1 1 46 46" fill="currentColor"><g transform="rotate(-8 24 28)"><path d="M43.5 24.2C43.5 22 41.5 20.8 39 20.6L31 20.4C30 18.4 26.5 18.4 25.5 20.4L9 21.4H5V24.2L24 27.2H38.5C41.5 27.2 43.5 26.4 43.5 24.2Z"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="20" y="13.6" width="14" height="2.0" rx="0.8"/><line x1="25" y1="15.4" x2="26.5" y2="19.5" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><line x1="29.5" y1="15.4" x2="30" y2="19" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><rect x="21" y="26.4" width="13" height="1.8" rx="0.8"/><line x1="22" y1="15.4" x2="22" y2="26.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><line x1="32.5" y1="15.4" x2="32.5" y2="26.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><line x1="32.5" y1="27" x2="34" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="34" cy="33.6" r="2.3"/><line x1="7.5" y1="23.8" x2="7" y2="25.6" stroke="currentColor" stroke-width="0.9" stroke-linecap="round"/><circle cx="7" cy="26.2" r="1.1"/></g></symbol>
|
|
38
|
+
<symbol id="a-ag-plane" viewBox="1 1 46 46" fill="currentColor"><g transform="rotate(-8 24 28)"><path d="M43.5 24.4C43.5 22.2 42 21.4 40 21.2L37 18.8H31.5L28.5 15.6C27.5 14.8 24.5 14.8 23.5 15.8L21.5 19.6L9 21.4H5V24.2L24 27.6H38.5C41.5 27.6 43.5 26.6 43.5 24.4Z"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="20" y="26.4" width="14.5" height="2.0" rx="0.8"/><rect x="19.5" y="29.4" width="15.5" height="0.8" rx="0.4"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><line x1="32.5" y1="27" x2="34" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="34" cy="33.6" r="2.3"/><line x1="7.5" y1="23.8" x2="7" y2="25.6" stroke="currentColor" stroke-width="0.9" stroke-linecap="round"/><circle cx="7" cy="26.2" r="1.1"/></g></symbol>
|
|
39
|
+
<symbol id="a-floatplane" viewBox="1 1 46 46" fill="currentColor"><path d="M43.5 24.2C43.5 22 41.5 20.8 39 20.6L35 18.6H24.5L9 21.4H5V24.2L24 27.2H38.5C41.5 27.2 43.5 26.4 43.5 24.2Z"/><path d="M34.2 19.3L37.6 21H33.8V19.3ZM25.2 19.3H32.8V21H25.2Z" style="fill:var(--avatar-bg,#fff)"/><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="21.5" y="16.6" width="13.0" height="2.0" rx="0.8"/><line x1="31" y1="18.4" x2="27" y2="26.4" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><rect x="44.4" y="15.5" width="1.2" height="17.4" rx="0.6"/><circle cx="44.2" cy="24.2" r="1.4"/><path d="M13 32.4H38C41 32.4 42.6 31.4 43.4 29.8L44 30.6C43.4 33 41.4 34.8 38 34.8H15L13 33.8Z"/><line x1="22" y1="27" x2="21" y2="32.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><line x1="33.5" y1="27" x2="34.5" y2="32.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/></symbol>
|
|
40
|
+
<symbol id="a-single-turboprop" viewBox="1 1 46 46" fill="currentColor"><path d="M45 24.4C45 22.6 43.6 21.6 41.6 21.4L33 20.8L30 18.4H21L7 21.2H3.6V24L22 27.4H41.6C43.8 27.4 45 26.4 45 24.4Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M29.2 19.1L31 20.6H28.4V19.1Z"/><rect x="21.6" y="19.1" width="5.8" height="1.5" rx="0.3"/></g><rect x="35.5" y="19.6" width="2.5" height="2.0" rx="0.5"/><path d="M3.6 21.4L2.6 11.6H6.6L13 21Z"/><rect x="1.2" y="21" width="10.4" height="1.4" rx="0.7"/><rect x="18" y="16.4" width="14" height="2.0" rx="0.8"/><line x1="28" y1="18.2" x2="24.6" y2="26.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><path d="M17 27.4H34C35.4 27.4 36 28 36 28.8C36 29.6 35.4 30.2 34 30.2H19Z"/><rect x="45.6" y="15.4" width="1.2" height="18.0" rx="0.6"/><line x1="40" y1="27.4" x2="40" y2="31.6" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="40" cy="33.2" r="1.8"/><line x1="26" y1="30" x2="27" y2="32" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="27" cy="33.4" r="2.1"/></symbol>
|
|
41
|
+
<symbol id="a-twin" viewBox="1 1 46 46" fill="currentColor"><path d="M45 24.6C45 22.8 43 21.6 40 21.2L35.4 18.6H24.5L9 21.4H5V24.2L24 27.2H40C43 27.2 45 26.4 45 24.6Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M34.6 19.3L37.8 21H34.2V19.3Z"/><rect x="25.2" y="19.3" width="7.8" height="1.7" rx="0.3"/></g><path d="M5 21.6L4 12.6H7.6L14 21Z"/><rect x="2.5" y="21.2" width="10.0" height="1.4" rx="0.7"/><rect x="19" y="26.4" width="14" height="2.0" rx="0.8"/><path d="M20 24.2H34.6C37.2 24.2 38.4 25.8 38.4 27.6C38.4 29.4 37.2 31 34.6 31H20Z"/><ellipse cx="38.4" cy="27.6" rx="0.8" ry="7"/></symbol>
|
|
42
|
+
<symbol id="a-business-jet" viewBox="1 1 46 46" fill="currentColor"><path d="M46.6 24.8C45 22.6 42.6 21.2 39 20.8L36 19.2H20L7 21.2H4V24.4L20 27H38C42.6 27 45.6 26.2 46.6 24.8Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M37.8 20.2L39.8 21.2H37.2Z"/><circle cx="32" cy="21.2" r="0.8"/><circle cx="29" cy="21.2" r="0.8"/><circle cx="26" cy="21.2" r="0.8"/><circle cx="23" cy="21.4" r="0.8"/></g><path d="M4.4 21.4L5.4 10.6H8.4L13.6 21Z"/><rect x="2.6" y="9.8" width="8.8" height="1.4" rx="0.7"/><path d="M9 17.4H17C19 17.4 20 18.4 20 19.4C20 20.4 19 21.4 17 21.4H9Z"/><path d="M18 26.4L30 26.2L34 27.8L22 28.4Z"/></symbol>
|
|
43
|
+
<symbol id="a-airliner" viewBox="1 1 46 46" fill="currentColor"><path d="M47 24.6C46 22.4 44 21.2 41 21.2H8L3.4 18.6H1V24.4L6 27.4H41C44 27.4 46.4 26.2 47 24.6Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M42 22.2L44.4 23.2H41.6Z"/><circle cx="10" cy="23" r="0.55"/><circle cx="13" cy="23" r="0.55"/><circle cx="16" cy="23" r="0.55"/><circle cx="19" cy="23" r="0.55"/><circle cx="22" cy="23" r="0.55"/><circle cx="25" cy="23" r="0.55"/><circle cx="28" cy="23" r="0.55"/><circle cx="31" cy="23" r="0.55"/><circle cx="34" cy="23" r="0.55"/><circle cx="37" cy="23" r="0.55"/></g><path d="M1.4 19L1 8.8H4.4L11.2 21.2Z"/><rect x="0" y="20.4" width="8.6" height="1.4" rx="0.7"/><path d="M18 26.6L30 26.4L34 28.4L22 29Z"/><path d="M24 28.2H31C32.6 28.2 33.4 29 33.4 30C33.4 31 32.6 31.8 31 31.8H24Z"/></symbol>
|
|
44
|
+
<symbol id="a-helicopter" viewBox="1 1 46 46" fill="currentColor"><path d="M39 26.4C39 21.4 36 18.4 31 18.4H27L24.6 16.4H18.6L16 19L4.6 21.6V23.4L19 25.4C19.6 28.4 21.6 30 24.6 30H35.4C37.6 30 39 28.6 39 26.4Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M31.4 19.8C35 19.8 37.4 22.4 37.6 25.8H32Z"/><rect x="25.4" y="20.6" width="4.0" height="4.4" rx="0.6"/></g><rect x="22.6" y="12.6" width="1.8" height="4" rx="0.5"/><rect x="4" y="11.4" width="40" height="1.4" rx="0.7"/><path d="M4.8 22L3 13.6H5.6L8.8 21.6Z"/><rect x="9" y="21.4" width="6" height="1.2" rx="0.5"/><circle cx="4.4" cy="17.4" r="2.6" fill="none" stroke="currentColor" stroke-width="0.8"/><line x1="25" y1="30" x2="24.4" y2="33" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><line x1="35" y1="30" x2="35.6" y2="33" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><rect x="20" y="32.8" width="20" height="1.2" rx="0.6"/></symbol>
|
|
45
|
+
<symbol id="a-heavy-helicopter" viewBox="1 1 46 46" fill="currentColor"><path d="M43 26C43 22 40.4 19.6 36.4 19.4L33 17.4H17.4L15 19.6L3.6 20.4V22.8L15 24.4V28.4C15 29.4 15.8 30 17 30H39.4C41.6 30 43 28.6 43 26Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M37 20.8C39.6 21 41.2 22.6 41.6 25H37.4Z"/><rect x="30" y="21.4" width="4.4" height="3.0" rx="0.5"/><rect x="23.4" y="21.4" width="4.4" height="3.0" rx="0.5"/><rect x="17.6" y="21.4" width="4.0" height="3.0" rx="0.5"/></g><path d="M14.6 17.4H34.6L33 15.6H17Z"/><rect x="24.4" y="11.4" width="2.0" height="4.4" rx="0.5"/><rect x="2.4" y="10.4" width="44.6" height="1.4" rx="0.7"/><path d="M4 21L2.4 12.6H5.4L9 20.6Z"/><rect x="5" y="19.4" width="7" height="1.2" rx="0.5"/><line x1="37" y1="30" x2="37" y2="32.6" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="37" cy="34" r="1.8"/><line x1="21" y1="30" x2="21" y2="32.6" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><circle cx="21" cy="34" r="1.9"/><circle cx="4.6" cy="23.6" r="1"/></symbol>
|
|
46
|
+
<symbol id="a-multirotor-drone" viewBox="1 1 46 46" fill="currentColor"><g transform="translate(24 24) scale(.84) translate(-24 -24)"><line x1="11" y1="11" x2="37" y2="37" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/><line x1="37" y1="11" x2="11" y2="37" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/><circle cx="11" cy="11" r="7.4" fill="none" stroke="currentColor" stroke-width="1.3"/><circle cx="37" cy="11" r="7.4" fill="none" stroke="currentColor" stroke-width="1.3"/><circle cx="11" cy="37" r="7.4" fill="none" stroke="currentColor" stroke-width="1.3"/><circle cx="37" cy="37" r="7.4" fill="none" stroke="currentColor" stroke-width="1.3"/><circle cx="11" cy="11" r="1.6"/><circle cx="37" cy="11" r="1.6"/><circle cx="11" cy="37" r="1.6"/><circle cx="37" cy="37" r="1.6"/><rect x="18.4" y="17" width="11.2" height="14" rx="3"/><g style="fill:var(--avatar-bg,#fff)"><rect x="20.6" y="19.6" width="6.8" height="4.4" rx="1.4"/></g><rect x="9" y="40.6" width="30" height="1.4" rx="0.7"/></g></symbol>
|
|
47
|
+
<symbol id="a-fixed-wing-drone" viewBox="1 1 46 46" fill="currentColor"><g transform="translate(24 24) scale(.84) translate(-24 -24)"><path d="M24 6C25.6 6 26.6 7.6 26.6 10V36H21.4V10C21.4 7.6 22.4 6 24 6Z"/><rect x="2" y="17" width="44" height="4.4" rx="1.4"/><rect x="11" y="9" width="2" height="26" rx="1"/><rect x="35" y="9" width="2" height="26" rx="1"/><circle cx="12" cy="9" r="4.4" fill="none" stroke="currentColor" stroke-width="1.1"/><circle cx="12" cy="35" r="4.4" fill="none" stroke="currentColor" stroke-width="1.1"/><circle cx="36" cy="9" r="4.4" fill="none" stroke="currentColor" stroke-width="1.1"/><circle cx="36" cy="35" r="4.4" fill="none" stroke="currentColor" stroke-width="1.1"/><rect x="17" y="36" width="14" height="2" rx="0.8"/><ellipse cx="24" cy="40" rx="5.4" ry="1"/></g></symbol>
|
|
48
|
+
<symbol id="a-glider" viewBox="1 1 46 46" fill="currentColor"><path d="M46 24.4C46 23 44 22.2 41 21.8L36 20.2C34.4 19.4 31 19.4 29.6 20.4L28 21.4L8 22.6H4.4V24.6L8 25.2L28 27H40C44 27 46 25.8 46 24.4Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M35.8 21.4C34.6 20.4 31.6 20.4 30.4 21.4Z"/></g><path d="M4.6 22.8L5.6 12H8.4L12 22.6Z"/><rect x="3.4" y="11.2" width="8.2" height="1.2" rx="0.6"/><rect x="22" y="22.2" width="11" height="1.4" rx="0.6"/><circle cx="30.4" cy="28" r="1.6"/></symbol>
|
|
49
|
+
<symbol id="a-balloon" viewBox="1 1 46 46" fill="currentColor"><path d="M24 2.6C32.6 2.6 38.6 8.4 38.6 16.4C38.6 23.6 31.6 29 27.2 32.6H20.8C16.4 29 9.4 23.6 9.4 16.4C9.4 8.4 15.4 2.6 24 2.6Z"/><g style="fill:var(--avatar-bg,#fff)"><path d="M19.6 4.4C17.4 9 17 20 21.4 31.6H22.6C19.4 20 19.8 9 21.6 3.8Z"/><path d="M28.4 4.4C30.6 9 31 20 26.6 31.6H25.4C28.6 20 28.2 9 26.4 3.8Z"/></g><line x1="21" y1="32.6" x2="21.6" y2="38.6" stroke="currentColor" stroke-width="0.7" stroke-linecap="round"/><line x1="27" y1="32.6" x2="26.4" y2="38.6" stroke="currentColor" stroke-width="0.7" stroke-linecap="round"/><rect x="20.4" y="38.2" width="7.2" height="6.0" rx="0.8"/></symbol>
|
|
50
|
+
<symbol id="a-trike" viewBox="1 1 46 46" fill="currentColor"><path d="M2 17.6L42 8.4C43.6 8.2 44.6 9 44.2 10.2L43.6 11.4L4 19.8Z"/><line x1="26" y1="13.6" x2="24" y2="25" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/><line x1="26" y1="13.6" x2="34.6" y2="22.6" stroke="currentColor" stroke-width="0.9" stroke-linecap="round"/><line x1="26" y1="13.6" x2="30.6" y2="23.4" stroke="currentColor" stroke-width="0.9" stroke-linecap="round"/><line x1="30.6" y1="23.4" x2="34.6" y2="22.6" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/><path d="M38 27.4C38 25.4 36 24 33 24H24L20 25V29.4H34C36.6 29.4 38 28.8 38 27.4Z"/><ellipse cx="18.4" cy="27.2" rx="1" ry="6.2"/><line x1="34" y1="29.4" x2="35" y2="32.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><circle cx="35" cy="34.2" r="1.8"/><line x1="23" y1="29.4" x2="22" y2="32.6" stroke="currentColor" stroke-width="1" stroke-linecap="round"/><circle cx="22" cy="34.2" r="1.9"/></symbol>
|
|
51
|
+
<symbol id="a-powered-parachute" viewBox="1 1 46 46" fill="currentColor"><path d="M4 13C10 4 38 4 44 13L41.6 14.6C35.6 8 12.4 8 6.4 14.6Z"/><line x1="7" y1="14" x2="22" y2="30" stroke="currentColor" stroke-width="0.6" stroke-linecap="round"/><line x1="17" y1="8.4" x2="23" y2="30" stroke="currentColor" stroke-width="0.6" stroke-linecap="round"/><line x1="31" y1="8.4" x2="25" y2="30" stroke="currentColor" stroke-width="0.6" stroke-linecap="round"/><line x1="41" y1="14" x2="26" y2="30" stroke="currentColor" stroke-width="0.6" stroke-linecap="round"/><path d="M34 32C34 30.2 32 29 29 29H20L16 30V34H30C32.6 34 34 33.4 34 32Z"/><circle cx="14.4" cy="31" r="5.2" fill="none" stroke="currentColor" stroke-width="1"/><circle cx="29" cy="36.4" r="1.7"/><circle cx="20" cy="36.4" r="1.8"/></symbol>
|
|
52
|
+
</svg>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Things added together (add-rows): its "+ Add …" (add-rows-add) draws a row from its template at the list's end, the
|
|
2
|
+
// cursor in its first field, and a row's Remove (add-row-drop) takes it off, telling the form it changed. Its button
|
|
3
|
+
// (add-rows-save), where it has one, shows while a row is there and counts them: data-one with one, data-many with
|
|
4
|
+
// %{count} for more. Without the script, the rows the page drew are all there are. ES5 alone.
|
|
5
|
+
(function () {
|
|
6
|
+
// A page with two boxes may link the script twice: its clicks are heard once.
|
|
7
|
+
if (window.easyAddRows || !document.querySelectorAll || !document.addEventListener) { return; }
|
|
8
|
+
window.easyAddRows = true;
|
|
9
|
+
|
|
10
|
+
function each(list, callback) { for (var i = 0; i < list.length; i++) { callback(list[i]); } }
|
|
11
|
+
|
|
12
|
+
function count(box) {
|
|
13
|
+
var save = box.querySelector('.add-rows-save');
|
|
14
|
+
if (!save) { return; }
|
|
15
|
+
var n = box.querySelectorAll('.add-rows-list .add-row').length;
|
|
16
|
+
save.hidden = n === 0;
|
|
17
|
+
save.textContent = n === 1 ? save.getAttribute('data-one') : save.getAttribute('data-many').replace('%{count}', n);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
document.addEventListener('click', function (event) {
|
|
21
|
+
var button = event.target.closest && event.target.closest('.add-rows-add, .add-row-drop');
|
|
22
|
+
var box = button && button.closest('.add-rows');
|
|
23
|
+
if (!box) { return; }
|
|
24
|
+
if (button.classList.contains('add-row-drop')) {
|
|
25
|
+
var form = box.closest('form');
|
|
26
|
+
var row = button.closest('.add-row');
|
|
27
|
+
row.parentNode.removeChild(row);
|
|
28
|
+
if (form) { form.dispatchEvent(new Event('change', { bubbles: true })); }
|
|
29
|
+
} else {
|
|
30
|
+
var added = box.querySelector('template').content.firstElementChild.cloneNode(true);
|
|
31
|
+
box.querySelector('.add-rows-list').appendChild(added);
|
|
32
|
+
var first = added.querySelector('input, select, textarea');
|
|
33
|
+
if (first) { first.focus(); }
|
|
34
|
+
}
|
|
35
|
+
count(box);
|
|
36
|
+
});
|
|
37
|
+
each(document.querySelectorAll('.add-rows'), count);
|
|
38
|
+
})();
|