Skip to content

Commit c6e0cdb

Browse files
committed
Adding drupal behaviors to storybook and possibility to load storybook's js and css directly from libraries.yml
1 parent 4fa7b14 commit c6e0cdb

File tree

27 files changed

+269
-104
lines changed

27 files changed

+269
-104
lines changed

packages/kaizen-cg/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ Once [kaizen-tg](https://www.npmjs.com/package/@skilld/kaizen-tg) is installed,
1717
1. `cd [themename_dir]`
1818
2. `yarn cc` and follow instructions
1919

20+
## Should know
21+
1. Every component's js uses Drupal.behaviors structure and it works in storybook same way as in Drupal.
22+
2023
## Recommendations
2124

2225
1. Please follow BEM methodology when you are creating component. More about BEM's namings [here](http://getbem.com/naming/)

packages/kaizen-cg/_templates/component/new/component-script.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,36 @@ to: <%= h.src() %>/packages/components/<%= h.changeCase.lower(h.inflection.plura
55
* @file
66
* This is component script template.
77
*/
8+
(({ behaviors }) => {
9+
<% if (typeof themeName != 'undefined') { %>behaviors.<%= h.changeCase.snakeCase(themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %> = {<% } else { %>behaviors.<%= h.changeCase.snakeCase(h.themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %> = {<% } %>
10+
attach: (context, settings) => {
11+
const customConfig =
12+
settings &&
13+
settings.behaviors &&
14+
<% if (typeof themeName != 'undefined') { %>settings.behaviors.<%= h.changeCase.snakeCase(themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %> &&
15+
settings.behaviors.<%= h.changeCase.snakeCase(themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %>.entries
16+
? settings.behaviors.<%= h.changeCase.snakeCase(themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %>.entries
17+
: '';
18+
<% } else { %>settings.behaviors.<%= h.changeCase.snakeCase(h.themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %> &&
19+
settings.behaviors.<%= h.changeCase.snakeCase(h.themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %>.entries
20+
? settings.behaviors.<%= h.changeCase.snakeCase(h.themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %>.entries
21+
: '';<% } %>
22+
const config = {
23+
entries: [
24+
{
25+
className: '<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>',
26+
},
27+
...customConfig,
28+
],
29+
processingName: '<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>',
30+
};
831

9-
export default ({
10-
className = '<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>',
11-
processingName = className,
12-
context = document,
13-
} = {}) => {
14-
once(processingName, `.${className}`, context).forEach((el) => {
15-
// eslint-disable-next-line no-console
16-
console.log(el);
17-
});
18-
};
32+
config.entries.forEach((entry) => {
33+
once(config.processingName, entry.className, context).forEach((el) => {
34+
// eslint-disable-next-line no-console
35+
console.log(el);
36+
});
37+
})
38+
},
39+
};
40+
})(Drupal);

packages/kaizen-cg/_templates/component/new/component.stories.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
to: <%= h.src() %>/packages/components/<%= h.changeCase.lower(h.inflection.pluralize(component_type)) %>/<%= h.changeCase.lower(h.inflection.dasherize(name)) %>/<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>.stories.js
33
---
44
import './<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>.css';
5-
import <%= h.inflection.camelize(name.replace(/ /g, '').replace(/-/g, '_'), true) %> from './<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>.js';
5+
import './<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>.js';
66
import drupalAttribute from 'drupal-attribute';
77
import { useEffect } from '@storybook/client-api';
88

@@ -19,9 +19,11 @@ export default {
1919
// uncomment next line if you want to define it.
2020
// argTypes: {},
2121
};
22-
23-
data.svgSpritePath = window.svgSpritePath;
24-
22+
<% if (typeof themeName != 'undefined') { %>
23+
data.<%= h.changeCase.snakeCase(themeName) %>SvgSpritePath = window.<%= h.changeCase.snakeCase(themeName) %>SvgSpritePath;
24+
<% } else { %>
25+
data.<%= h.changeCase.snakeCase(h.themeName) %>SvgSpritePath = window.<%= h.changeCase.snakeCase(h.themeName) %>SvgSpritePath;
26+
<% } %>
2527
export const basic = (args = {}) => {
2628
const attributes = new drupalAttribute();
2729
attributes.addClass(['<%= h.changeCase.lower(component_type).charAt(0) %>-<%= h.changeCase.lower(h.inflection.dasherize(name)) %>']);
@@ -39,7 +41,8 @@ export const basic = (args = {}) => {
3941
}
4042
data.attributes = attributes;
4143
useEffect(() => {
42-
<%= h.inflection.camelize(name.replace(/ /g, '').replace(/-/g, '_'), true) %>();
44+
// Uncomment next line if you need javascript in your component.
45+
<% if (typeof themeName != 'undefined') { %>// Drupal.behaviors.<%= h.changeCase.snakeCase(themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %>.attach();<% } else { %>// Drupal.behaviors.<%= h.changeCase.snakeCase(h.themeName) %>_storybook_<%= h.changeCase.lower(component_type).charAt(0) %>_<%= h.changeCase.snakeCase(h.inflection.dasherize(name)) %>.attach();<% } %>
4346
}, [args]);
4447
return template({
4548
...data,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
// see types of prompts:
3+
// https://github.com/enquirer/enquirer/tree/master/examples
4+
//
5+
const cliArgs = process.argv.slice(2);
6+
const themeName = cliArgs ? cliArgs.join(',').split('--theme_name=').pop().split(',')[0] : '';
7+
8+
module.exports = {
9+
prompt: ({ inquirer, args }) => {
10+
const askForThemeName = themeName ? '' : {
11+
type: 'input',
12+
name: 'themeName',
13+
message: "What's your theme name?",
14+
required: true
15+
};
16+
const questions = [
17+
askForThemeName,
18+
{
19+
type: 'input',
20+
name: 'name',
21+
message: "What's your component name?",
22+
required: true
23+
},
24+
{
25+
type: 'select',
26+
name: 'component_type',
27+
message: 'What type of component?',
28+
choices: ['Atom', 'Molecule', 'Organism', 'Template', 'Helper'],
29+
},
30+
{
31+
type: 'input',
32+
name: 'description',
33+
message: "What's your component description?",
34+
initial: "Component description placeholder"
35+
}
36+
];
37+
38+
return inquirer.prompt(questions)
39+
},
40+
}

packages/kaizen-cg/_templates/component/new/prompt.js

Lines changed: 0 additions & 25 deletions
This file was deleted.

packages/kaizen-cg/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
const hygen = require("hygen");
33
const path = require("path");
44

5+
const cliArgs = process.argv.slice(2);
6+
const themeName = cliArgs ? cliArgs.join(',').split('--theme_name=').pop().split(',')[0] : '';
7+
58
const config = {
69
templates: `${__dirname}/_templates`,
710
cwd: __dirname,
@@ -14,6 +17,7 @@ const config = {
1417
helpers: {
1518
relative: (from, to) => path.relative(from, to),
1619
src: () => process.cwd(),
20+
themeName,
1721
},
1822
};
1923

packages/kaizen-cg/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@skilld/kaizen-cg",
3-
"version": "2.0.0-alpha.3",
3+
"version": "2.0.0-alpha.4",
44
"description": "Kaizen component generator",
55
"bin": "index.js",
66
"main": "index.js",

packages/kaizen-core/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ This component helps you to easily simulate link to some wrapper, based on link
1818
Example of usage:
1919
```
2020
<div class="m-teaser" data-h-entity-fake-link-container>
21+
<div class="m-teaser__content">... Some content ... </div>
2122
<a class="m-teaser__link" href="#" data-h-entity-fake-link-target>Lorem ipsum</a>
2223
</div>
2324
```
24-
Note that you can even skip this attribute `data-h-entity-fake-link-target` if your clickable-container contains only one link inside. The script has a fallback in that case and it will take first link in the tree if target data attribute wasn't added for the link.
25+
Note that you can even skip this attribute `data-h-entity-fake-link-target` for your link if your clickable-container contains only one link inside. The script has a fallback in that case and it will take first link in the tree if target data attribute wasn't added for the link.
2526

2627
In storybook you have to call this script for your story like this:
2728
```

packages/kaizen-core/helpers/entity-fake-link/h-entity-fake-link.js

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ const fakeLinkProcessed = (el, link) => {
2020
el.setAttribute('data-href', link.getAttribute('href'));
2121
el.setAttribute(
2222
'aria-label',
23-
link.hasAttribute('title') ? link.getAttribute('title') : link.textContent.replace(/\s+/g, ' ').trim(),
23+
link.hasAttribute('title')
24+
? link.getAttribute('title')
25+
: link.textContent.replace(/\s+/g, ' ').trim(),
2426
);
2527
el.setAttribute(
2628
'data-target',
@@ -39,23 +41,43 @@ const fakeLinkProcessed = (el, link) => {
3941
});
4042
};
4143

42-
export default ({
43-
wrapperData = '[data-h-entity-fake-link-container]',
44-
targetData = '[data-h-entity-fake-link-target]',
45-
processingName = 'h-entity-fake-link',
46-
context = document,
47-
} = {}) => {
48-
once(processingName, wrapperData, context).forEach((el) => {
49-
// Multiple links inside of element you want to wrap is not expected
50-
// with this script. So it searches only the first matched.
51-
let link = el.querySelector(`a${targetData}[href]`);
52-
if (!link) {
53-
// Fallback search. If targetData is not defined, then let's try
54-
// to catch just first matched link.
55-
link = el.querySelector('a[href]');
56-
}
57-
if (link) {
58-
fakeLinkProcessed(el, link);
59-
}
60-
});
61-
};
44+
(({ behaviors }) => {
45+
behaviors.kaizen_core_h_entity_fake_link = {
46+
attach: (context, settings) => {
47+
const customConfig =
48+
settings &&
49+
settings.behaviors &&
50+
settings.behaviors.kaizen_core_h_entity_fake_link &&
51+
settings.behaviors.kaizen_core_h_entity_fake_link.entries
52+
? settings.behaviors.kaizen_core_h_entity_fake_link.entries
53+
: '';
54+
const config = {
55+
entries: [
56+
{
57+
wrapperData: '[data-h-entity-fake-link-container]',
58+
targetData: '[data-h-entity-fake-link-target]',
59+
},
60+
...customConfig,
61+
],
62+
processingName: 'h-entity-fake-link',
63+
};
64+
config.entries.forEach((entry) => {
65+
once(config.processingName, entry.wrapperData, context).forEach(
66+
(el) => {
67+
// Multiple links inside of element you want to wrap is not expected
68+
// with this script. So it searches only the first matched.
69+
let link = el.querySelector(`a${entry.targetData}[href]`);
70+
if (!link) {
71+
// Fallback search. If targetData is not defined, then let's try
72+
// to catch just first matched link.
73+
link = el.querySelector('a[href]');
74+
}
75+
if (link) {
76+
fakeLinkProcessed(el, link);
77+
}
78+
},
79+
);
80+
});
81+
},
82+
};
83+
})(Drupal);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Helper / Entity-fake-link
22

3-
This component helps to simulate link around element, which contains original link.
3+
This component helps to simulate link around element, based on some original link.

0 commit comments

Comments
 (0)