|
| 1 | +--- |
| 2 | +prev: |
| 3 | + text: 'Webflow' |
| 4 | + link: '/webflow' |
| 5 | +next: |
| 6 | + text: 'Type Guards' |
| 7 | + link: '/type-guards' |
| 8 | +--- |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | +# Components |
| 13 | + |
| 14 | +## `CopyJSONButton` |
| 15 | + |
| 16 | +This util is used to copy the data of a Webflow component which can then be pasted into Webflow designer directly. |
| 17 | + |
| 18 | +| param | value | |
| 19 | +| ----------------------------------- | ---------------------------------------------------- | |
| 20 | +| element: `HTMLElement` | The element to trigger the copy | |
| 21 | +| copyData: `Record<string, unknown>` | The JSON data of the element that needs to be copied | |
| 22 | +| successText?: `string` | Text to showcase on successful copy | |
| 23 | +| errorText?: `string` | Text to shocase when an error occurs while copying | |
| 24 | +| successCSSClass?: `string` | Class to be added on the element on successful copy. | |
| 25 | + |
| 26 | +> How to get `copyData`? |
| 27 | +> |
| 28 | +> 1. Open your webflow designer |
| 29 | +> 2. Paste this code in your dev tools console |
| 30 | +> |
| 31 | +> ```js |
| 32 | +> document.addEventListener('copy', ({ clipboardData }) => { |
| 33 | +> const webflowData = clipboardData.getData('application/json'); |
| 34 | +> |
| 35 | +> const type = 'text/plain'; |
| 36 | +> const blob = new Blob([webflowData], { type }); |
| 37 | +> const data = [ |
| 38 | +> new ClipboardItem({ |
| 39 | +> [type]: blob, |
| 40 | +> }), |
| 41 | +> ]; |
| 42 | +> |
| 43 | +> navigator.clipboard.write(data); |
| 44 | +> console.log(webflowData); |
| 45 | +> }); |
| 46 | +> ``` |
| 47 | +> |
| 48 | +> 3. Now, select/click/focus on the Webflow component that you wish to copy the JSON data of. |
| 49 | +> 4. Press `CTRL+C` or `CMD+C` |
| 50 | +> 5. Check the console logs in the dev tools and copy the JSON data from there to further use it in your code as per your prefernece. |
| 51 | +
|
| 52 | +### Available methods: |
| 53 | +
|
| 54 | +- `updateCopyData()`: |
| 55 | + Updates the JSON data to be copied. |
| 56 | +
|
| 57 | + | param | value | |
| 58 | + | -------------------------------------- | --------------------------------------------- | |
| 59 | + | newCopyData: `Record<string, unknown>` | The new JSON data of the element to be copied | |
| 60 | +
|
| 61 | +- `updateTextContent()`: |
| 62 | + Updates the button's text content. |
| 63 | +
|
| 64 | + | param | value | |
| 65 | + | ----------------- | ---------------------------- | |
| 66 | + | newText: `string` | The new text to be displayed | |
| 67 | +
|
| 68 | +Example: |
| 69 | +
|
| 70 | +```ts |
| 71 | +import { CopyJSONButton } from '@finsweet/ts-utils'; |
| 72 | +
|
| 73 | +// The JSON data of the element to be copied |
| 74 | +import copyData from './webflow-component.json'; |
| 75 | +
|
| 76 | +window.Webflow ||= []; |
| 77 | +window.Webflow.push(() => { |
| 78 | + // The element to trigger the copy on click |
| 79 | + const element = document.querySelector<HTMLAnchorElement>('#fs-trigger'); |
| 80 | + if (!element) return; |
| 81 | +
|
| 82 | + // Initializing the method |
| 83 | + new CopyJSONButton({ element, copyData, successText: 'Copied! Paste in Webflow' }); |
| 84 | +}); |
| 85 | +``` |
| 86 | +
|
| 87 | +## `Interaction` |
| 88 | + |
| 89 | +This util acts as a controller for elements that have a Webflow Ix2 click interaction binded to it. |
| 90 | + |
| 91 | +| param | value | |
| 92 | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | |
| 93 | +| element: `HTMLElement / string` | Webflow element/ selector that has the Mouse Click interaction | |
| 94 | +| duration?: `Number / Partial<Interaction['duration']>` | Optionally, the duration can be explicitly set so the trigger methods will return an awaitable Promise. | |
| 95 | + |
| 96 | +### Available methods: |
| 97 | + |
| 98 | +- `isActive()`: |
| 99 | + Checks if the interaction is active. |
| 100 | + | Return value: `Boolean` | |
| 101 | + | ------ | |
| 102 | + |
| 103 | +- `isRunning()`: |
| 104 | + Checks if the interaction is running. |
| 105 | + | Return value: `Boolean` | |
| 106 | + | ------ | |
| 107 | + |
| 108 | +- `untilFinished()`: |
| 109 | + Returns a promise that fulfills when the current running interaction has finished |
| 110 | + | Return value: `An awaitable Promise` | |
| 111 | + | ------ | |
| 112 | + |
| 113 | +Example: |
| 114 | + |
| 115 | +```ts |
| 116 | +import { Interaction } from '@finsweet/ts-utils'; |
| 117 | + |
| 118 | +window.Webflow ||= []; |
| 119 | +window.Webflow.push(async () => { |
| 120 | + // Trigger element that has a Mouse Click interaction |
| 121 | + const triggerElement = document.querySelector('[fs-element="ix2-trigger"]') as HTMLElement; |
| 122 | + |
| 123 | + // Initializing Interaction |
| 124 | + const interaction = new Interaction({ element: triggerElement, duration: 300 }); |
| 125 | + |
| 126 | + // This won't run because the first click hasn't been triggered yet. |
| 127 | + interaction.trigger('second'); |
| 128 | + |
| 129 | + // Triggers the first click interaction, only when allowed. Returns a Promise that can be awaited. |
| 130 | + await interaction.trigger('first'); |
| 131 | + |
| 132 | + // Returns if the first click has been fired. |
| 133 | + interaction.isActive(); |
| 134 | + |
| 135 | + // Returns if the interaction is still running. |
| 136 | + interaction.isRunning(); |
| 137 | + |
| 138 | + // Triggers the second click interaction, only when allowed. Returns a Promise that can be awaited. |
| 139 | + interaction.trigger('second'); |
| 140 | + |
| 141 | + // Returns a Promise that resolves once the ongoing interaction (if triggered) finishes. |
| 142 | + await interaction.untilFinished(); |
| 143 | +}); |
| 144 | +``` |
| 145 | + |
| 146 | + |
| 147 | +## `DisplayController` |
| 148 | + |
| 149 | +This util helps to show/hide an element using built-in fade animations or no animations at all. It also works with Webflow interactions. |
| 150 | + |
| 151 | +| param | value | |
| 152 | +| -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 153 | +| element: `HTMLElement / string` | The main element | |
| 154 | +| interaction?: `InteractionParams` | If the display must be controlled through a Webflow interaction | |
| 155 | +| displayProperty?: `typeof DisplayController['displayProperties'][number];` | The display property of the element when displayed. Not applicable when interaction parameters ara passed to the instance, as it's assumed that the Webflow interaction will set the display property. Defaults to `block`. | |
| 156 | +| noTransition?: `boolean` | If set to true, the element will be straight showed / hidden without any transition. | |
| 157 | +| startsHidden?: `boolean` | If set to true, the element will be set to `display: none`. | |
| 158 | + |
| 159 | +| Available displayProperty options: | |
| 160 | +| ---------------------------------- | |
| 161 | +| `block` | |
| 162 | +| `flex` | |
| 163 | +| `grid` | |
| 164 | +| `inline-block` | |
| 165 | +| `inline` | |
| 166 | + |
| 167 | +### Available methods: |
| 168 | + |
| 169 | +- `isVisible()`: |
| 170 | + Checks if element is visible |
| 171 | + |
| 172 | + | Return value: `Boolean` | |
| 173 | + | ----------------------- | |
| 174 | + |
| 175 | +- `show()` |
| 176 | + Displays the element |
| 177 | + |
| 178 | + | Return value: `An awaitable Promise` | |
| 179 | + | ------------------------------------ | |
| 180 | + |
| 181 | +- `hide()` |
| 182 | + Hides the element |
| 183 | + |
| 184 | + | Return value: `An awaitable Promise` | |
| 185 | + | ------------------------------------ | |
| 186 | + |
| 187 | +Example: |
| 188 | + |
| 189 | +```ts |
| 190 | +import { DisplayController } from '@finsweet/ts-utils'; |
| 191 | + |
| 192 | +const API_BASE = 'https://pokeapi.co/api/v2'; |
| 193 | +const API_URI = '/pokemon/ditto'; |
| 194 | +window.Webflow ||= []; |
| 195 | +window.Webflow.push(async () => { |
| 196 | + // Quering the target element, which in this case is a loader |
| 197 | + const loadingElement = document.querySelector('#fs-loader') as HTMLElement; |
| 198 | + |
| 199 | + // Initialises DiplayController |
| 200 | + const loadingDisplayController = new DisplayController({ |
| 201 | + element: loadingElement, |
| 202 | + displayProperty: 'block', |
| 203 | + noTransition: true, |
| 204 | + startsHidden: true, |
| 205 | + }); |
| 206 | + |
| 207 | + // shows the loader while the API is fetching the data |
| 208 | + loadingDisplayController.show(); |
| 209 | + |
| 210 | + // awaiting the API Promise |
| 211 | + const pokemons = await fetch(API_BASE + API_URI); |
| 212 | + |
| 213 | + // hides the loader once the API is done fetching the data |
| 214 | + loadingDisplayController.hide(); |
| 215 | +}); |
| 216 | +``` |
0 commit comments