lookbook 0.4.1 → 0.4.5
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/README.md +220 -53
- data/app/assets/lookbook/css/app.css +14 -8
- data/app/assets/lookbook/js/app.js +2 -0
- data/app/assets/lookbook/js/nav.js +5 -6
- data/app/assets/lookbook/js/page.js +5 -0
- data/app/assets/lookbook/js/utils/morph.js +3 -0
- data/app/assets/lookbook/js/workbench/param.js +19 -0
- data/app/controllers/lookbook/app_controller.rb +24 -7
- data/app/helpers/lookbook/application_helper.rb +6 -1
- data/app/helpers/lookbook/preview_helper.rb +7 -0
- data/app/views/lookbook/workbench/_inspector.html.erb +6 -1
- data/app/views/lookbook/workbench/inspector/_params.html.erb +28 -0
- data/app/views/lookbook/workbench/inspector/params/_select.html.erb +8 -0
- data/app/views/lookbook/workbench/inspector/params/_text.html.erb +8 -0
- data/app/views/lookbook/workbench/inspector/params/_textarea.html.erb +8 -0
- data/app/views/lookbook/workbench/inspector/params/_toggle.html.erb +13 -0
- data/lib/lookbook/engine.rb +6 -0
- data/lib/lookbook/features.rb +24 -0
- data/lib/lookbook/params.rb +110 -0
- data/lib/lookbook/parser.rb +1 -1
- data/lib/lookbook/preview.rb +1 -1
- data/lib/lookbook/preview_controller.rb +2 -3
- data/lib/lookbook/preview_example.rb +13 -1
- data/lib/lookbook/preview_group.rb +5 -1
- data/lib/lookbook/taggable.rb +2 -2
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +2 -0
- data/public/lookbook-assets/app.css +129 -7
- data/public/lookbook-assets/app.js +46 -8
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 676b8a78237532971ec7d22d7265b3da7d3b896aa8020d7ab1c514edc3859b45
|
4
|
+
data.tar.gz: dfb016bf927d7492afdeacd3b10a2425563e227b5cbd4ebd4d3f7a5bfa97609f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e5aeb26c2db3322e7aa127e176b691744d5af3cfbd207159f65d0e9dee1362382f418b07bda2fa7b75d7f85b35f522efe106707e665c6e12f9ab5e4ca1f4cd1
|
7
|
+
data.tar.gz: be2908ed45f9645dd9387adf6547c8c45ba262310325438197de22d6db9909705fa3e45de0912914004d516c4546618ccc73fd96fea3fbdc86f2affa5e7ebb3d
|
data/README.md
CHANGED
@@ -28,6 +28,7 @@ Lookbook uses [RDoc/Yard-style comment tags](#annotating-preview-files) to exten
|
|
28
28
|
- Auto-updating UI when component or preview files are updated _(Rails v6.0+ only)_
|
29
29
|
- Use comment tag annotations for granular customisation of the preview experience
|
30
30
|
- Fully compatible with standard the ViewComponent preview system
|
31
|
+
- [**Experimental**] In-browser live editable preview parameters (similar to Storybook Controls/Knobs)
|
31
32
|
|
32
33
|
## Lookbook demo
|
33
34
|
|
@@ -76,7 +77,7 @@ Lookbook parses [Yard-style comment tags](https://rubydoc.info/gems/yard/file/do
|
|
76
77
|
|
77
78
|
```ruby
|
78
79
|
# @label Basic Button
|
79
|
-
# @display bg_color
|
80
|
+
# @display bg_color #fff
|
80
81
|
class ButtonComponentPreview < ViewComponent::Preview
|
81
82
|
|
82
83
|
# Primary button
|
@@ -90,11 +91,24 @@ class ButtonComponentPreview < ViewComponent::Preview
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
94
|
+
# Button with icon
|
95
|
+
# ----------------
|
96
|
+
# This example uses dynamic preview parameters
|
97
|
+
# which can be edited live in the Lookbook UI
|
98
|
+
#
|
99
|
+
# @param text
|
100
|
+
# @param icon select [heart, cog, alert]
|
101
|
+
def icon(text: "Spread the love", icon: "heart")
|
102
|
+
render ButtonComponent.new(icon: icon) do
|
103
|
+
text
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
93
107
|
# Inverted button
|
94
108
|
# ---------------
|
95
109
|
# For light-on-dark screens
|
96
110
|
#
|
97
|
-
# @display bg_color
|
111
|
+
# @display bg_color #000
|
98
112
|
def secondary
|
99
113
|
render ButtonComponent.new(style: :inverted) do
|
100
114
|
"Click me"
|
@@ -141,54 +155,41 @@ end
|
|
141
155
|
|
142
156
|
The following Lookbook-specific tags are available for use:
|
143
157
|
|
144
|
-
* `@label
|
145
|
-
* `@
|
146
|
-
*
|
147
|
-
*
|
158
|
+
* [`@label`](#label-tag)
|
159
|
+
* [`@display`](#display-tag)
|
160
|
+
* [`@!group ... @!endgroup`](#group-tag)
|
161
|
+
* [`@hidden`](#hidden-tag)
|
162
|
+
* [`@param`](#param-tag) [⚠️ **experimental!** - requires [feature opt-in](#experimental-features) ⚠️]
|
148
163
|
|
149
|
-
|
164
|
+
<h3 id="label-tag">🏷 @label</h3>
|
150
165
|
|
151
166
|
Used to replace the auto-generated navigation label for the item with `<text>`.
|
152
167
|
|
153
|
-
> Available for preview classes & example methods.
|
154
|
-
|
155
168
|
```ruby
|
156
|
-
|
157
|
-
class FooComponentPreview < ViewComponent::Preview
|
158
|
-
|
159
|
-
# @label Example Label
|
160
|
-
def default
|
161
|
-
end
|
162
|
-
end
|
169
|
+
@label <text>
|
163
170
|
```
|
164
171
|
|
165
|
-
|
166
|
-
|
167
|
-
Used to temporarily exclude an item from the Lookbook navigation. The item will still be accessible via it's URL.
|
168
|
-
|
169
|
-
Can be useful when a component (or a variant of a component) is still in development and is not ready to be shared with the wider team.
|
170
|
-
|
171
|
-
> Available for both preview classes & example methods.
|
172
|
+
> Available for preview classes & example methods.
|
172
173
|
|
173
174
|
```ruby
|
174
|
-
# @
|
175
|
+
# @label Preview Label
|
175
176
|
class FooComponentPreview < ViewComponent::Preview
|
176
177
|
|
177
|
-
# @
|
178
|
+
# @label Example Label
|
178
179
|
def default
|
179
180
|
end
|
180
181
|
end
|
181
182
|
```
|
182
183
|
|
183
|
-
|
184
|
+
<h3 id="display-tag">🏷 @display</h3>
|
184
185
|
|
185
186
|
The `@display` tag lets you pass custom parameters to your preview layout so that the component preview can be customised on a per-example basis.
|
186
187
|
|
187
188
|
```ruby
|
188
|
-
# @display bg_color
|
189
|
+
# @display bg_color #eee
|
189
190
|
class FooComponentPreview < ViewComponent::Preview
|
190
191
|
|
191
|
-
# @display max_width
|
192
|
+
# @display max_width 500px
|
192
193
|
# @display wrapper true
|
193
194
|
def default
|
194
195
|
end
|
@@ -198,13 +199,11 @@ end
|
|
198
199
|
The `@display` tag can be applied at the preview (class) or at the example (method) level, and takes the following format:
|
199
200
|
|
200
201
|
```ruby
|
201
|
-
|
202
|
+
@display <key> <value>
|
202
203
|
```
|
203
204
|
|
204
205
|
- `<key>` must be a valid Ruby hash key name, without quotes or spaces
|
205
|
-
- `<value>`
|
206
|
-
|
207
|
-
> [See below for some examples](#some-display-value-examples) of valid and invalid `@display` values.
|
206
|
+
- `<value>` will be parsed using the [Ruby YAML parser](https://yaml.org/YAML_for_ruby.html) to resolve the value
|
208
207
|
|
209
208
|
These display parameters can then be accessed via the `params` hash in your preview layout using `params[:lookbook][:display][<key>]`:
|
210
209
|
|
@@ -244,27 +243,7 @@ config.lookbook.preview_display_params = {
|
|
244
243
|
|
245
244
|
Globally defined display params will be available to all previews. Any preview or example-level `@display` values with the same name will take precedence and override a globally-set one.
|
246
245
|
|
247
|
-
|
248
|
-
|
249
|
-
Valid:
|
250
|
-
|
251
|
-
```ruby
|
252
|
-
# @display body_classes "bg-red border border-4 border-green"
|
253
|
-
# @display wrap_in_container true
|
254
|
-
# @display emojis_to_show 4
|
255
|
-
# @display page_title "Special example title"
|
256
|
-
```
|
257
|
-
|
258
|
-
Invalid:
|
259
|
-
|
260
|
-
```ruby
|
261
|
-
# @display body_classes 'bg-red border border-4 border-green' [❌ single quotes]
|
262
|
-
# @display wrap_in_container should_wrap [❌ unquoted string, perhaps trying to call a method]
|
263
|
-
# @display page title "Special example title" [❌ space in key]
|
264
|
-
# @display bg_color #fff [❌ colors need quotes around them, it's not CSS!]
|
265
|
-
```
|
266
|
-
|
267
|
-
### 🔖 `@!group <name> ... @!endgroup`
|
246
|
+
<h3 id="group-tag">🔖 `@!group ... @!endgroup`</h3>
|
268
247
|
|
269
248
|
For smaller components, it can often make sense to render a set of preview examples in a single window, rather than representing them as individual items in the navigation which can start to look a bit cluttered.
|
270
249
|
|
@@ -310,6 +289,167 @@ The example above would display the `Sizes` examples grouped together on a singl
|
|
310
289
|
|
311
290
|
You can have as many groups as you like within a single preview class, but each example can only belong to one group.
|
312
291
|
|
292
|
+
<h3 id="hidden-tag">🏷 `@hidden`</h3>
|
293
|
+
|
294
|
+
Used to temporarily exclude an item from the Lookbook navigation. The item will still be accessible via it's URL.
|
295
|
+
|
296
|
+
Can be useful when a component (or a variant of a component) is still in development and is not ready to be shared with the wider team.
|
297
|
+
|
298
|
+
> Available for both preview classes & example methods.
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
# @hidden
|
302
|
+
class FooComponentPreview < ViewComponent::Preview
|
303
|
+
|
304
|
+
# @hidden
|
305
|
+
def default
|
306
|
+
end
|
307
|
+
end
|
308
|
+
```
|
309
|
+
|
310
|
+
<h3 id="param-tag"> 🚧 @param (experimental)</h3>
|
311
|
+
|
312
|
+
> ⚠️ This feature is currently flagged as an **experimental** feature which requires [feature opt-in](#experimental-features) to use. Its API and implementation may change in the future.
|
313
|
+
|
314
|
+
The `@param` tag provides the ability to specify **editable preview parameters** which can be changed in the Lookbook UI in order to customise the rendered output on the fly, much like the [Controls (knobs) addon](https://storybook.js.org/addons/@storybook/addon-controls) for Storybook.
|
315
|
+
|
316
|
+
Each `@param` will have an associated form field generated for it. The values for each field will be handled as [dynamic preview params](https://viewcomponent.org/guide/previews.html#:~:text=It%E2%80%99s%20also%20possible%20to%20set%20dynamic%20values%20from%20the%20params%20by%20setting%20them%20as%20arguments%3A) when rendering the example.
|
317
|
+
|
318
|
+
The `@param` tag takes the following format:
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
@param <name> <input_type> <opts?>
|
322
|
+
```
|
323
|
+
|
324
|
+
- `<name>` - name of the dynamic preview param
|
325
|
+
- `<input_type>` - input field type to generate in the UI
|
326
|
+
- `<opts?>` - YAML-encoded field options, used for some field types
|
327
|
+
|
328
|
+
#### Input types
|
329
|
+
|
330
|
+
The following **input field types** are available for use:
|
331
|
+
|
332
|
+
📝 **Text-style inputs** - Single line fields, useful for short strings of text or numbers.
|
333
|
+
|
334
|
+
```ruby
|
335
|
+
@param <name> text
|
336
|
+
@param <name> email
|
337
|
+
@param <name> number
|
338
|
+
@param <name> url
|
339
|
+
@param <name> tel
|
340
|
+
```
|
341
|
+
|
342
|
+
> The above types only differ in the validation constraints they impose on the input field.
|
343
|
+
|
344
|
+
📝 **Textarea** - Multi-line textarea field for longer-form content.
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
@param <name> textarea
|
348
|
+
```
|
349
|
+
|
350
|
+
📝 **Select box** - Dropdown select field for selecting from a list of known options.
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
@param <name> select <options>
|
354
|
+
```
|
355
|
+
|
356
|
+
`<options>` should be a [YAML array](https://yaml.org/YAML_for_ruby.html#simple_inline_array) of options which must be formatted in the same style as the input for Rails' [`options_for_select`](https://apidock.com/rails/v6.0.0/ActionView/Helpers/FormOptionsHelper/options_for_select) helper:
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
# Basic options:
|
360
|
+
# @param theme select [primary, secondary, danger]
|
361
|
+
|
362
|
+
# With custom labels (each item itself an array of [label, value]):
|
363
|
+
# @param theme select [[Primary theme, primary], [Secondary theme, secondary], [Danger theme, danger]]
|
364
|
+
|
365
|
+
# With empty option (`~` in YAML)
|
366
|
+
# @param theme select [~, primary, secondary, danger]
|
367
|
+
```
|
368
|
+
|
369
|
+
> **Note**: In most cases YAML does not require quoting of strings, however if you are running into issues check out the [Ruby YAML docs](https://yaml.org/YAML_for_ruby.html) for a complete syntax reference.
|
370
|
+
|
371
|
+
📝 **Toggle** - On/off switch for toggling boolean values.
|
372
|
+
|
373
|
+
```ruby
|
374
|
+
@param <name> toggle
|
375
|
+
```
|
376
|
+
|
377
|
+
#### Default values
|
378
|
+
|
379
|
+
Default values are specified as part of the preview example method parameters in the usual Ruby way:
|
380
|
+
|
381
|
+
```ruby
|
382
|
+
def button(content: "Click me", theme: "primary", arrow: false)
|
383
|
+
# ...
|
384
|
+
end
|
385
|
+
```
|
386
|
+
|
387
|
+
These will be used as the default values for the param fields.
|
388
|
+
|
389
|
+
> Note that the default values are **not** evaluated at runtime, so you cannot use method calls to generate the defaults. Only static default values are supported.
|
390
|
+
|
391
|
+
#### Type casting values
|
392
|
+
|
393
|
+
Most dynamic param values are passed to the example method as strings, with the following exceptions:
|
394
|
+
|
395
|
+
- `toggle` input - values are cast to booleans
|
396
|
+
- `number` input - values are cast to integers
|
397
|
+
|
398
|
+
In some cases, you may want to type cast the parameter value to something else (for example a `Symbol`) before using it when initializing the component.
|
399
|
+
|
400
|
+
To help with this, a `type` option can be specified in the `@param` definition to automatically cast the dynamic value to a different type:
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
# @param <name> [<type>] <input_type> <opts?>
|
404
|
+
```
|
405
|
+
|
406
|
+
In the example below, the value of the `theme` param (by default a string) will be automatically cast to a Symbol, ready for use in instantiating the component.
|
407
|
+
|
408
|
+
```ruby
|
409
|
+
# @param theme [Symbol] select [primary, secondary, danger]
|
410
|
+
def default(theme: :primary)
|
411
|
+
render Elements::ButtonComponent.new(theme: theme) do
|
412
|
+
"Click me"
|
413
|
+
end
|
414
|
+
end
|
415
|
+
```
|
416
|
+
|
417
|
+
The supported types to cast to are:
|
418
|
+
|
419
|
+
- `String` - *default for all except `toggle` inputs*
|
420
|
+
- `Boolean` - *default for `toggle` inputs*
|
421
|
+
- `Symbol`
|
422
|
+
- `Date`
|
423
|
+
- `DateTime`
|
424
|
+
- `Integer`
|
425
|
+
- `Float`
|
426
|
+
|
427
|
+
The following structured types are also available but should be considered **experimental** - you may run into bugs!
|
428
|
+
|
429
|
+
- `Hash` - *value string converted to Hash using the Ruby YAML parser*
|
430
|
+
- `Array` - *value string converted to Array using the Ruby YAML parser*
|
431
|
+
|
432
|
+
#### Full example:
|
433
|
+
|
434
|
+
```ruby
|
435
|
+
class ButtonComponentPreview < ViewComponent::Preview
|
436
|
+
|
437
|
+
# The params defined below will be editable in the UI:
|
438
|
+
#
|
439
|
+
# @param content text
|
440
|
+
# @param theme select [primary, secondary, danger]
|
441
|
+
# @param arrow toggle
|
442
|
+
def default(content: "Click me", theme: "primary", arrow: true)
|
443
|
+
render Elements::ButtonComponent.new(theme: theme, arrow: arrow) do
|
444
|
+
content
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
end
|
449
|
+
```
|
450
|
+
|
451
|
+
<img src=".github/assets/dynamic_params.png">
|
452
|
+
|
313
453
|
### Adding notes
|
314
454
|
|
315
455
|
All comment text other than tags will be treated as markdown and rendered in the **Notes** panel for that example in the Lookbook UI.
|
@@ -352,6 +492,33 @@ If you wish to add additional paths to listen for changes in, you can use the `l
|
|
352
492
|
config.lookbook.listen_paths << Rails.root.join('app/other/directory')
|
353
493
|
```
|
354
494
|
|
495
|
+
<h3 id="experimental-features">Experimental features opt-in</h3>
|
496
|
+
|
497
|
+
Some features may occasionally be released behind a 'experimental' feature flag while they are being tested and refined, to allow people to try them out and provide feedback.
|
498
|
+
|
499
|
+
> ⚠️ **Please note:** Experimental features should be considered to be **subject to extensive change** and breaking changes to them may be made within point releases - these features are **not** considered to be covered by [semver](https://semver.org/) whilst flagged as 'experimental'. ⚠️
|
500
|
+
|
501
|
+
#### Opting into specific features (recommended)
|
502
|
+
|
503
|
+
To opt into individual experimental features, include the name of the feature in the `experimental_features` config option:
|
504
|
+
|
505
|
+
```ruby
|
506
|
+
config.lookbook.experimental_features = ["feature_name"]
|
507
|
+
```
|
508
|
+
|
509
|
+
The current experimental features that can be opted into are:
|
510
|
+
|
511
|
+
- `params`: Live-editable, dynamic preview parameters ([read more](#param-tag)). Include `"params"` in the `experimental_features` config option to opt in.
|
512
|
+
|
513
|
+
#### Opting into all experimental features (not recommended!)
|
514
|
+
|
515
|
+
If you want to live life on the bleeding-edge you can opt-in to all current **and future** experimental features (usual caveats apply):
|
516
|
+
|
517
|
+
```ruby
|
518
|
+
config.lookbook.experimental_features = true
|
519
|
+
```
|
520
|
+
|
521
|
+
|
355
522
|
## Keyboard shortcuts
|
356
523
|
|
357
524
|
Lookbook provides a few keyboard shortcuts to help you quickly move around the UI.
|
@@ -35,14 +35,6 @@
|
|
35
35
|
fill: none;
|
36
36
|
}
|
37
37
|
|
38
|
-
.h-fill {
|
39
|
-
height: fill-available;
|
40
|
-
}
|
41
|
-
|
42
|
-
.min-h-fill {
|
43
|
-
min-height: fill-available;
|
44
|
-
}
|
45
|
-
|
46
38
|
::-webkit-scrollbar {
|
47
39
|
width: 8px;
|
48
40
|
height: 8px;
|
@@ -63,3 +55,17 @@
|
|
63
55
|
@apply bg-gray-400;
|
64
56
|
}
|
65
57
|
}
|
58
|
+
|
59
|
+
@layer utilities {
|
60
|
+
.h-fill {
|
61
|
+
height: fill-available;
|
62
|
+
}
|
63
|
+
|
64
|
+
.min-h-fill {
|
65
|
+
min-height: fill-available;
|
66
|
+
}
|
67
|
+
|
68
|
+
.form-input {
|
69
|
+
@apply border-gray-300 text-gray-700 focus:ring-indigo-300 focus:border-indigo-300 rounded-sm text-sm w-full;
|
70
|
+
}
|
71
|
+
}
|
@@ -9,6 +9,7 @@ import page from "./page";
|
|
9
9
|
import workbench from "./workbench";
|
10
10
|
import preview from "./workbench/preview";
|
11
11
|
import inspector from "./workbench/inspector";
|
12
|
+
import param from "./workbench/param";
|
12
13
|
import nav from "./nav";
|
13
14
|
import navNode from "./nav/node";
|
14
15
|
import navLeaf from "./nav/leaf";
|
@@ -56,6 +57,7 @@ Alpine.data("navLeaf", navLeaf);
|
|
56
57
|
Alpine.data("workbench", workbench);
|
57
58
|
Alpine.data("preview", preview);
|
58
59
|
Alpine.data("inspector", inspector);
|
60
|
+
Alpine.data("param", param);
|
59
61
|
Alpine.data("clipboard", clipboard);
|
60
62
|
Alpine.data("sizeObserver", sizeObserver);
|
61
63
|
Alpine.data("split", split);
|
@@ -22,13 +22,12 @@ export default function () {
|
|
22
22
|
});
|
23
23
|
},
|
24
24
|
navigate(path) {
|
25
|
-
|
26
|
-
path = path.currentTarget.href;
|
27
|
-
}
|
28
|
-
history.pushState({}, null, path);
|
29
|
-
this.$dispatch("popstate");
|
25
|
+
this.navigateTo(path instanceof Event ? path.currentTarget.href : path);
|
30
26
|
},
|
31
|
-
focusFilter() {
|
27
|
+
focusFilter($event) {
|
28
|
+
if ($event.target.tagName === "INPUT") {
|
29
|
+
return;
|
30
|
+
}
|
32
31
|
this.currentFocus = this.$refs.filter;
|
33
32
|
setTimeout(() => this.$refs.filter.focus(), 0);
|
34
33
|
},
|
@@ -27,7 +27,12 @@ export default function page() {
|
|
27
27
|
render() {
|
28
28
|
if (this.ready) {
|
29
29
|
morph(this.$el, store.doc.getElementById(this.$el.id));
|
30
|
+
this.$dispatch("document:patched");
|
30
31
|
}
|
31
32
|
},
|
33
|
+
navigateTo(path) {
|
34
|
+
history.pushState({}, null, path);
|
35
|
+
this.$dispatch("popstate");
|
36
|
+
},
|
32
37
|
};
|
33
38
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
export default function param() {
|
2
|
+
return {
|
3
|
+
focused: false,
|
4
|
+
setFocus() {
|
5
|
+
if (this.focused && this.$el.focus) {
|
6
|
+
this.$el.focus();
|
7
|
+
}
|
8
|
+
},
|
9
|
+
update(name, value) {
|
10
|
+
const searchParams = new URLSearchParams(window.location.search);
|
11
|
+
searchParams.set(name, value);
|
12
|
+
const path = location.href.replace(location.search, "");
|
13
|
+
this.navigateTo(`${path}?${searchParams.toString()}`);
|
14
|
+
},
|
15
|
+
validate() {
|
16
|
+
return this.$el.reportValidity ? this.$el.reportValidity() : true;
|
17
|
+
},
|
18
|
+
};
|
19
|
+
}
|
@@ -8,7 +8,7 @@ module Lookbook
|
|
8
8
|
prepend_view_path File.expand_path("../../views/lookbook", __dir__)
|
9
9
|
|
10
10
|
layout "layouts/app"
|
11
|
-
helper Lookbook::
|
11
|
+
helper Lookbook::ApplicationHelper
|
12
12
|
|
13
13
|
before_action :find_preview, only: [:preview, :show]
|
14
14
|
before_action :find_example, only: [:preview, :show]
|
@@ -96,8 +96,7 @@ module Lookbook
|
|
96
96
|
}
|
97
97
|
end
|
98
98
|
set_params
|
99
|
-
|
100
|
-
preview_controller.render_in_layout_to_string("lookbook/preview/group", {examples: examples}, layout)
|
99
|
+
preview_controller.render_in_layout_to_string("lookbook/preview/group", {examples: examples}, @preview.lookbook_layout)
|
101
100
|
else
|
102
101
|
set_params(@example)
|
103
102
|
preview_controller.params[:path] = "#{@preview.preview_name}/#{@example.name}".chomp("/")
|
@@ -106,6 +105,15 @@ module Lookbook
|
|
106
105
|
end
|
107
106
|
|
108
107
|
def set_params(example = nil)
|
108
|
+
if example.present? && enabled?(:params)
|
109
|
+
# cast known params to type
|
110
|
+
example.params.each do |param|
|
111
|
+
if preview_controller.params.key?(param[:name])
|
112
|
+
preview_controller.params[param[:name]] = Lookbook::Params.cast(preview_controller.params[param[:name]], param[:type])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
# set display params
|
109
117
|
example_params = example.nil? ? @preview.display_params : example.display_params
|
110
118
|
preview_controller.params.merge!({
|
111
119
|
lookbook: {
|
@@ -114,10 +122,6 @@ module Lookbook
|
|
114
122
|
})
|
115
123
|
end
|
116
124
|
|
117
|
-
def current_layout
|
118
|
-
preview_controller.send :_layout, preview_controller.lookup_context, [:html]
|
119
|
-
end
|
120
|
-
|
121
125
|
def assign_inspector
|
122
126
|
@inspector = {
|
123
127
|
panes: {
|
@@ -144,6 +148,15 @@ module Lookbook
|
|
144
148
|
}
|
145
149
|
}
|
146
150
|
}
|
151
|
+
if enabled?(:params)
|
152
|
+
@inspector[:panes][:params] = {
|
153
|
+
label: "Params",
|
154
|
+
template: "params",
|
155
|
+
hotkey: "p",
|
156
|
+
items: @source.many? ? [] : @example.params,
|
157
|
+
disabled: @source.many? || @example.params.none?
|
158
|
+
}
|
159
|
+
end
|
147
160
|
end
|
148
161
|
|
149
162
|
def assign_nav
|
@@ -179,5 +192,9 @@ module Lookbook
|
|
179
192
|
controller.response = response
|
180
193
|
@preview_controller ||= controller
|
181
194
|
end
|
195
|
+
|
196
|
+
def enabled?(feature)
|
197
|
+
Lookbook::Features.enabled?(feature)
|
198
|
+
end
|
182
199
|
end
|
183
200
|
end
|
@@ -8,7 +8,12 @@ module Lookbook
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def markdown(text)
|
11
|
-
Markdown.new(
|
11
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, {
|
12
|
+
tables: true,
|
13
|
+
fenced_code_blocks: true,
|
14
|
+
disable_indented_code_blocks: true
|
15
|
+
})
|
16
|
+
markdown.render(text).html_safe
|
12
17
|
end
|
13
18
|
|
14
19
|
def highlight(source, language)
|
@@ -20,7 +20,12 @@
|
|
20
20
|
</div>
|
21
21
|
<div class="flex-auto overflow-auto bg-gray-50">
|
22
22
|
<% panes.each do |key, props| %>
|
23
|
-
<div class="flex flex-col h-full relative" x-show="active('<%= key %>')" x-
|
23
|
+
<div class="flex flex-col h-full relative" x-show="active('<%= key %>')" x-effect="
|
24
|
+
if ($store.inspector.active === '<%= key %>') {
|
25
|
+
const input = $el.querySelector('[data-param-input]');
|
26
|
+
if (input) setTimeout(() => input.focus(), 0)
|
27
|
+
}
|
28
|
+
" x-cloak>
|
24
29
|
<% if props[:clipboard].present? %>
|
25
30
|
<%= render "shared/clipboard" do %><%= h props[:clipboard].strip %><% end %>
|
26
31
|
<% end %>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% if @example.type == :group %>
|
2
|
+
<div class="p-4 prose prose-sm">
|
3
|
+
<em class='opacity-50'>Params are not supported for grouped previews.</em>
|
4
|
+
</div>
|
5
|
+
<% elsif items.none? %>
|
6
|
+
<div class="p-4 prose prose-sm">
|
7
|
+
<em class='opacity-50'>No params configured.</em>
|
8
|
+
</div>
|
9
|
+
<% else %>
|
10
|
+
<div class="py-3">
|
11
|
+
<% items.each do |param| %>
|
12
|
+
<div class="px-4 py-3" x-data="param" @document:patched="setFocus">
|
13
|
+
<div class="flex items-start max-w-[800px]">
|
14
|
+
<div class="w-[200px] flex-none py-2">
|
15
|
+
<label for="param-<%= param[:name] %>" class="font-bold"><%= param[:name].titleize %></label>
|
16
|
+
</div>
|
17
|
+
<div class="flex-grow" @focus="focussed = true" @blur="focussed = false">
|
18
|
+
<%= render "workbench/inspector/params/#{param[:input]}",
|
19
|
+
**param,
|
20
|
+
value: params.key?(param[:name]) ? params[param[:name]] : param[:default],
|
21
|
+
id: "#{@example.id}-param-#{param[:name]}"
|
22
|
+
%>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
27
|
+
</div>
|
28
|
+
<% end %>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div id="<%= id %>" x-init="checked = <%= value == "true" ? "true" : "false" %>" data-param-input>
|
2
|
+
<button type="button"
|
3
|
+
class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-400"
|
4
|
+
:class="{'bg-indigo-500': checked, 'bg-gray-300': !checked}"
|
5
|
+
role="switch"
|
6
|
+
@click.stop="checked = !checked; update('<%= name %>', checked)">
|
7
|
+
<span
|
8
|
+
aria-hidden="true"
|
9
|
+
class="pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"
|
10
|
+
:class="{'translate-x-5': checked, 'translate-x-0': !checked}"
|
11
|
+
></span>
|
12
|
+
</button>
|
13
|
+
</div>
|