-
Notifications
You must be signed in to change notification settings - Fork 1
Module
Prop | Type | Description |
---|---|---|
name |
String |
The name of the module |
[tag='div'] |
String |
HTML tag to use when rendering the module |
[modifiers] |
Array |
Modifiers to add to the rendered module |
[className] |
String |
CSS classes to add to the rendered module |
[before] |
React Element |
Content to render before the module |
[after] |
React Element |
Content to render after the module |
[id] |
String |
The id HTML attribute to add to the rendered module |
[href] |
String |
The href HTML attribute |
[data‑{attribute}] |
String |
Any data-attribute |
[on{Event}] |
Function |
Any valid GlobalEventHandler (you must use camelCase to be compatible with React) |
[modifierGlue='-'] |
String |
The glue to use when attaching modifiers to modules/components |
[componentGlue='_'] |
String |
The glue to use when attaching modifiers to modules/components |
[config] |
Object |
Configuration to use for module |
[init] |
Function |
Function to call on rendered DOM element |
[styleParser] |
Function |
Function to parse and apply styles |
[styles] |
Array |
Array of parameters to pass to the function defined by styleParser
|
[ui] |
* |
Placeholder property for Synergy framework |
<Module name='foo' modifierGlue='--' bar>My Module</Module>
<div class="foo--bar">My Module</div>
This must be set on
<Module>
and not<Component>
<Module name='foo' componentGlue='__'>
<Component name='bar'>My Component</Component>
</Module>
<div class="foo">
<div class="foo__bar">My Component</div>
</div>
- Automatically merged with config found under Window object
- Config is attached to the rendered DOM node
- Config is passed to
styleParser
function as the third parameter
// Some default pre-existing config attached to `Window`
// - `foo` must match whatever value you pass to `Props.name` on `<Module>`
window.foo.config = {
fizz: 'buzz',
someData: [1, 6, 35, 9]
}
// some custom config
const config = {
fizz: 'bang',
someData: window.foo.config.someData.concat([11]),
someMethod: () => { ... }
}
// As the `name` value is `foo`, it will fetch data from `window.foo.config`
<Module name='foo' config={config} id='myModule'>My Module</Module>
After rendering the module on the page you can now do:
var element = document.getElementById('myModule');
element.config.fizz; // returns 'bang'
element.config.someData; // returns [1, 6, 35, 9, 11]
element.config.someMethod(); // executes `someMethod()`
Overwrite the value of
props.name
when rendering the module (this allows the name used to reference the Module internally to be different from the name used when rendering the Module to the DOM)
<Module name='foo' config={{ name: 'namespaced-foo' }}>My Module</Module>
<div class="namespaced-foo">My Module</div>
A function that will be called when the component renders, where the first and only parameter will be the HTML element of the rendered component
init(node)
This property is used to pass a function which would be used to style the component, based off the values passed from the styles
prop, and gets invoked like so:
styleParser(node, ...props.styles)
...allowing your styleParser
function to contain any number of parameters as long as the first parameter expects the HTML element of the rendered component.
Polymorph
was built to be used as astyleParser
function to be used with Lucid
Instead of having to pass this prop every time, you can assign your styleParser
function to window.Synergy.styleParser
where it will automatically be picked up by the <Module>
component.
Rather than passing the parameters for the styleParser
function via Props.styles
, Lucid can fetch values from the Window
object and pass them in a pre-defined manner. If Props.styles
is not set, the styleParser
function will be executed like so:
styleParser(node, window.MODULE_NAME.layout, config, ui);
-
config
will be the module's configuration -
ui
will be the result of eitherProps.ui
orwindow.ui
An array of values to be passed as parameters for the
styleParser
function
@TODO
It's possible to render an element as multiple modules by passing additional module names as props, ensuring that the first letter is capitalised.
<Module name='blockquote' Alert>...</Module>
<div class="blockquote alert">...</div>
<Module name='blockquote' Alert='success'>...</Module>
<div class="blockquote alert-success">...</div>
<Module name='blockquote' Alert={['box', 'success']}>...</Module>
<div class="blockquote alert-box-success">...</div>
This feature was introduced for the Synergy framework but can be utilised independently
If you utilise the styleParser
property, or use Polymorph, then when you pass additional modules you will likely also want them to be styled as that module.
Lucid handles this use-case and requires only a bit of setup to work. Here's the relevant code from Lucid to handle this behaviour:
Object.keys(props).forEach(prop => {
const fistLetter = prop[0];
if (fistLetter === fistLetter.toUpperCase()) {
if (window[prop] && window[prop].layout && window[prop].config) {
node.namespace = node.namespace || prop;
styleParser(node, window[prop].layout, window[prop].config, ui);
}
}
});
Reference: /lucid/src/utilities/refHandler.js
From the above code, it can be identified that the following needs to exist for styleParser
to work on the additionally applied module:
-
Layout object/function for the additionally applied module, which should be attached to
window.MODULE_NAME.layout
(this needs to be done manually)- this will be passed as the second parameter to
styleParser
- this will be passed as the second parameter to
-
Configuration object for the additionally applied module, which should be attached to
window.MODULE_NAME.config
(this needs to be done manually)- this will passed as the third parameter to
styleParser
- this will passed as the third parameter to
-
MODULE_NAME
must have a capitalised first letter
You'll also notice a ui
reference in the above code; this is passed in <Module>
's constructor
method, and will either be the result returned from Props.ui, window.ui
, or undefined
- with the value being passed as the fourth parameter to the styleParser
.
window.ui = {
colors: {
primary: 'red',
secondary: 'blue'
}
}
window.Alert = {
layout: {
display: 'block'
},
config: {
color: 'red'
}
}
<Module name='blockquote' Alert>...</Module>
Now when the above <Module>
component is rendered, the styleParser function will be executed like so:
// `node` is the rendered DOM element of `<Module>`
styleParser(node, window.Alert.layout, window.Alert.config, window.ui);
Naturally without knowing what styleParser
does there is no result to show here, however for more context you can check out Polymorph, which was built as a styleParser
function for Lucid
.
For an example of where this feature is used consider looking at the Synergy framework, which is a toolkit consisting of Lucid, Polymorph and sQuery.
It's possible to add CSS classes to an element by passing them as props. In order for the <Module>
component to know what CSS classes are allowed, you must add them to a global window.Synergy.CssClassProps
array:
window.Synergy.CssClassProps = ['object', 'inline'];
Now in your React component you can do:
<Module name='accordion' object>...</Module>
<Module name='button' inline>...</Module>
<div class="accordion object">...</div>
<div class="button inline">...</div>
If window.Synergy.CssClassProps
wasn't defined (or it didn't contain the relevant values), object
and inline
would instead be treated as modifiers, and the output would be:
<div class="accordion-object">...</div>
<div class="button-inline">...</div>
You can automatically call an init
function on the rendered DOM element in the module's componentDidMount
lifecycle method by attaching the function to the init
property of your module's global object. This object needs to be created manually:
This will only take effect if Props.init is not defined
window.accordion = {
init: node => {
// do something with `node`
...
}
}
<Module name='accordion'>...</Module>
Now whenever a <Module>
component with a name
value of accordion
is mounted, the window.accordion.init
method will be called upon the rendered DOM element. This is equivalent to passing the same function to the <Module>
's init
prop.