Skip to content

Commit 5647715

Browse files
castastrophekylebuch8
authored andcommitted
Storybook updates (#268)
* Update pfe-accordion and pfe-card to dynamic approach * Add cta and tabs compatibility with new approach * Remove commented out code; optimize rendering with a shared util function * Update tabs with orientation fix * Fix fallback for booleans and update datetime to show knobs
1 parent b5481b2 commit 5647715

32 files changed

+931
-383
lines changed

.storybook/utils.js

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,203 @@
11
// This is a collection of functions to reuse within PFElements stories.
22

3+
// Automatic content generation
4+
// https://www.npmjs.com/package/lorem-ipsum
5+
const loremIpsum = require("lorem-ipsum");
6+
const cleaner = require("clean-html");
7+
8+
// Escape HTML to display markup as content
39
export function escapeHTML(html) {
410
const div = document.createElement("div");
511
const text = document.createTextNode(html);
612
div.appendChild(text);
713
return div.innerHTML;
814
}
15+
16+
// Convert a string to sentence case
17+
String.prototype.sentenceCase = function() {
18+
return this.charAt(0).toUpperCase() + this.slice(1);
19+
};
20+
21+
// Print attributes based on an object
22+
const listProperties = obj =>
23+
Object.entries(obj)
24+
.map(set => {
25+
let p = set[0];
26+
let v = set[1];
27+
let print = set[2] || true;
28+
return print && v && v !== "null" ? ` ${p}="${v}"` : "";
29+
})
30+
.join("");
31+
32+
// Create a tag based on a provided object
33+
export function customTag(obj) {
34+
return `<${obj.tag ? obj.tag : "div"} ${
35+
obj.slot ? `slot="${obj.slot}"` : ""
36+
}${listProperties(obj.attributes || {})}>${obj.content || autoContent()}</${
37+
obj.tag ? obj.tag : "div"
38+
}>`;
39+
}
40+
41+
// If a slot is a component or content, render that raw
42+
// if it's got a tag defined, run the custom tag function
43+
const renderSlots = (slots = []) =>
44+
slots.map(slot => (slot.content ? slot.content : "")).join("");
45+
46+
// Creates a component dynamically based on inputs
47+
export function component(tag, attributes = {}, slots = []) {
48+
return `<${tag}${listProperties(attributes)}>${
49+
slots.length > 0 ? renderSlots(slots) : autoContent()
50+
}</${tag}>`;
51+
}
52+
53+
// Create an automatic heading
54+
export function autoHeading(short = false) {
55+
let length = short ? Math.random() + 2 : Math.random() * 10 + 5;
56+
return loremIpsum({ count: length, units: "words" }).sentenceCase();
57+
}
58+
59+
// Create a set of automatic content
60+
export function autoContent(max = 5, min = 1, short = false) {
61+
return loremIpsum({
62+
count: Math.floor(Math.random() * max + min),
63+
sentenceUpperBound: short ? 5 : 15,
64+
paragraphUpperBound: short ? 2 : 7,
65+
units: "paragraphs",
66+
format: "html"
67+
});
68+
}
69+
70+
// Return Storybook knobs based on an object containing property definitions for the component
71+
export function autoPropKnobs(properties, bridge) {
72+
var binding = {};
73+
Object.entries(properties).forEach(prop => {
74+
let attr = prop[0];
75+
let title = prop[1].title || attr;
76+
let type = prop[1].type || "string";
77+
let defaultValue = prop[1].default;
78+
let options = prop[1].enum || [];
79+
let hidden = prop[1].hidden || false;
80+
81+
// Set the default method to text
82+
let method = "text";
83+
if (["boolean", "number", "object", "array", "date"].includes(type)) {
84+
method = type.toLowerCase();
85+
}
86+
87+
// If the property is not hidden from the user
88+
if (!hidden) {
89+
// If an array of options exists, create a select list
90+
if (options.length > 0) {
91+
let opts = {};
92+
// Convert the array into an object
93+
options.map(item => (opts[item] = item));
94+
95+
// If a default is not defined, add a null option
96+
if (defaultValue === "" || defaultValue === null) {
97+
opts.null = "none";
98+
defaultValue = null;
99+
}
100+
101+
// Create the knob
102+
binding[attr] = bridge.select(title, opts, defaultValue, "Attributes");
103+
} else {
104+
// Create the knob
105+
binding[attr] = bridge[method](title, defaultValue, "Attributes");
106+
}
107+
}
108+
});
109+
return binding;
110+
}
111+
112+
// Create knobs to render input fields for the slots
113+
export function autoContentKnobs(slots, bridge) {
114+
let binding = {};
115+
116+
Object.entries(slots).forEach(slot => {
117+
binding[slot[0]] = bridge.text(slot[1].title, slot[1].default, "Content");
118+
});
119+
120+
return binding;
121+
}
122+
123+
export function demo(markup) {
124+
// Prettify and clean the markup for rendering
125+
cleaner.clean(
126+
markup,
127+
{
128+
indent: " ",
129+
"remove-attributes": [],
130+
"break-around-tags": [
131+
"body",
132+
"blockquote",
133+
"br",
134+
"div",
135+
"h1",
136+
"h2",
137+
"h3",
138+
"h4",
139+
"h5",
140+
"h6",
141+
"head",
142+
"hr",
143+
"link",
144+
"meta",
145+
"p",
146+
"table",
147+
"title",
148+
"td",
149+
"tr",
150+
"a"
151+
],
152+
wrap: 0
153+
},
154+
html => (markup = html)
155+
);
156+
157+
// Return the rendered markup and the code snippet output
158+
return `${markup}`;
159+
}
160+
161+
export function code(markup) {
162+
// Prettify and clean the markup for rendering
163+
cleaner.clean(
164+
markup,
165+
{
166+
indent: " ",
167+
"remove-attributes": [],
168+
"break-around-tags": [
169+
"body",
170+
"blockquote",
171+
"br",
172+
"div",
173+
"h1",
174+
"h2",
175+
"h3",
176+
"h4",
177+
"h5",
178+
"h6",
179+
"head",
180+
"hr",
181+
"link",
182+
"meta",
183+
"p",
184+
"table",
185+
"title",
186+
"td",
187+
"tr",
188+
"a"
189+
],
190+
wrap: 0
191+
},
192+
html => (markup = html)
193+
);
194+
195+
// Return the rendered markup and the code snippet output
196+
return `<pre style="white-space: pre-wrap; padding: 20px 50px; background-color: #f0f0f0; font-weight: bold; border: 1px solid #bccc;">${escapeHTML(
197+
markup
198+
)}</pre>`;
199+
}
200+
201+
export function preview(markup) {
202+
return demo(markup) + code(markup);
203+
}

elements/pfe-accordion/pfe-accordion.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

elements/pfe-accordion/pfe-accordion.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

elements/pfe-accordion/pfe-accordion.story.js

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

0 commit comments

Comments
 (0)