diff --git a/.komment/00000.json b/.komment/00000.json new file mode 100644 index 00000000..b0921657 --- /dev/null +++ b/.komment/00000.json @@ -0,0 +1,256 @@ +[ + { + "name": "flatfile.listener.ts", + "path": "packages/listener/src/flatfile.listener.ts", + "content": { + "structured": { + "description": "A Flatfile Listener class that extends an EventHandler and provides various methods for subscribing to events, filtering by namespace, mounting/unmounting event drivers, and forking instances. The listener can be used with different event drivers such as Webhook, Websocket, and Serverless. It utilizes EventFilter and EventDriver classes from external packages.", + "items": [ + { + "id": "e7ed0802-de24-5d9d-504e-954945983709", + "ancestors": [], + "description": "Enables subscribing to events within a specific namespace and provides methods for filtering, creating, mounting, and unmounting event listeners using an Event Driver. It facilitates the handling of events by providing a flexible and reusable event listener infrastructure.", + "interfaces": [], + "superclass": "EventHandler", + "is_abstract": false, + "fields": [], + "name": "FlatfileListener", + "location": { + "start": 34, + "insert": 34, + "offset": " ", + "indent": 0, + "comment": null + }, + "item_type": "class", + "length": 58, + "docLength": null + }, + { + "id": "3c8f8688-6f4f-a7ad-0e45-2a36aac3ed9d", + "ancestors": [ + "e7ed0802-de24-5d9d-504e-954945983709" + ], + "description": "Filters an array-like object using a callback function and returns the result, passing two parameters: an array of strings representing namespaces and an optional callback function.", + "params": [ + { + "name": "namespaces", + "default_value": null, + "optional": false, + "type_name": "string | string[]", + "description": "Used for filtering purposes." + } + ], + "returns": { + "type_name": "Array", + "description": "A filtered array of objects based on the given `namespaces` and callback function `cb`." + }, + "usage": { + "language": "typescript", + "code": "const listener = FlatfileListener.create(() => {\n listener.namespace(['namespace1', 'namespace2'], (client) => {\n // namespace specific code\n });\n});\n", + "description": "" + }, + "name": "namespace", + "location": { + "start": 41, + "insert": 35, + "offset": " ", + "indent": 2, + "comment": { + "start": 34, + "end": 40 + } + }, + "item_type": "function", + "length": 3, + "docLength": 6 + }, + { + "id": "3ef1687e-8061-0787-394e-5c8c677208f3", + "ancestors": [ + "e7ed0802-de24-5d9d-504e-954945983709" + ], + "description": "Creates an instance of the same class with a given `EventFilter`, adds it as a node, and optionally calls a callback function with the created node as an argument. The method returns the created client instance.", + "params": [ + { + "name": "filter", + "default_value": null, + "optional": false, + "type_name": "EventFilter", + "description": "Used to specify filtering criteria." + } + ], + "returns": { + "type_name": "this", + "description": "An instance of the class that contains the method." + }, + "usage": { + "language": "typescript", + "code": "const flatfileListener = FlatfileListener.create((listener) => {\n listener.namespace('event namespace').filter({ namespaces: ['event namespace'] }, (client) => {\n // Event handling code here\n });\n});\n", + "description": "" + }, + "name": "filter", + "location": { + "start": 51, + "insert": 45, + "offset": " ", + "indent": 2, + "comment": { + "start": 44, + "end": 50 + } + }, + "item_type": "function", + "length": 6, + "docLength": 6 + }, + { + "id": "9557b21b-b4ac-9cad-b147-589ce839699a", + "ancestors": [ + "e7ed0802-de24-5d9d-504e-954945983709" + ], + "description": "Generates an instance of itself, calls a provided callback function with this instance as argument, and returns the instance. The type parameter `T` ensures that the method can only be called on constructors of types that extend `FlatfileListener`.", + "params": [ + { + "name": "cb", + "default_value": null, + "optional": false, + "type_name": "SubFn", + "description": "Callback function." + } + ], + "returns": { + "type_name": "T", + "description": "A constructor of FlatfileListener that has been initialized by calling the callback function with it as an argument." + }, + "usage": { + "language": "typescript", + "code": "const listener = FlatfileListener.create((client) => {\n client.namespace('myNamespace')\n})\n", + "description": "" + }, + "name": "create", + "location": { + "start": 63, + "insert": 58, + "offset": " ", + "indent": 2, + "comment": { + "start": 57, + "end": 62 + } + }, + "item_type": "function", + "length": 8, + "docLength": 5 + }, + { + "id": "574b75f4-4b2d-40bb-8f43-2a7f4690f9ee", + "ancestors": [ + "e7ed0802-de24-5d9d-504e-954945983709" + ], + "description": "Mounts an event handler for the provided `driver`. It binds the current object (`this`) to the driver's event handling mechanism, allowing it to receive and process events from the driver. The method returns the modified instance of `FlatfileListener`.", + "params": [ + { + "name": "driver", + "default_value": null, + "optional": false, + "type_name": "EventDriver", + "description": "Intended to provide event handling capabilities." + } + ], + "returns": { + "type_name": "this", + "description": "An instance of the current class. The exact nature and purpose of this object are not specified within the provided code snippet." + }, + "usage": { + "language": "typescript", + "code": "const listener = new FlatfileListener();\nlistener.mount(new EventDriver());\n", + "description": "\nMount attaches this client using an acceptable event driver." + }, + "name": "mount", + "location": { + "start": 75, + "insert": 72, + "offset": " ", + "indent": 2, + "comment": { + "start": 71, + "end": 74 + } + }, + "item_type": "function", + "length": 4, + "docLength": 3 + }, + { + "id": "ff766c70-5ac9-cca1-7e41-e597d6b52449", + "ancestors": [ + "e7ed0802-de24-5d9d-504e-954945983709" + ], + "description": "Unregisters an event handler from the underlying `EventDriver`. It removes the reference to the listener and returns the instance itself for further method chaining.", + "params": [ + { + "name": "driver", + "default_value": null, + "optional": false, + "type_name": "EventDriver", + "description": "Intended to unmount an event handler." + } + ], + "returns": { + "type_name": "this", + "description": "A reference to the object on which the function was called." + }, + "usage": { + "language": "typescript", + "code": "const flatfileListener = FlatfileListener.create((listener) => {\n listener.namespace('event namespace').on('some event', (data) => {\n // handle some event\n });\n});\nflatfileListener.mount(driver);\n// use the listener\nflatfileListener.unmount(driver);", + "description": "" + }, + "name": "unmount", + "location": { + "start": 83, + "insert": 80, + "offset": " ", + "indent": 2, + "comment": { + "start": 79, + "end": 82 + } + }, + "item_type": "function", + "length": 4, + "docLength": 3 + }, + { + "id": "3a1bfa77-9468-d9a1-f64b-a623266850a8", + "ancestors": [ + "e7ed0802-de24-5d9d-504e-954945983709" + ], + "description": "Returns a new instance of `FlatfileListener`. This allows for the creation of multiple instances of the same listener, which can be used to handle different tasks or events independently.", + "params": [], + "returns": { + "type_name": "object", + "description": "An instance of `FlatfileListener`." + }, + "usage": { + "language": "typescript", + "code": "const listener = new FlatfileListener()\nlistener.fork().namespace('test', (client) => {\n // Do something with client\n})\n", + "description": "\nMount the returned `FlatfileListener` instance to a driver." + }, + "name": "fork", + "location": { + "start": 88, + "insert": 88, + "offset": " ", + "indent": 2, + "comment": null + }, + "item_type": "function", + "length": 3, + "docLength": null + } + ] + } + } + } +] \ No newline at end of file diff --git a/.komment/komment.json b/.komment/komment.json new file mode 100644 index 00000000..336c77c4 --- /dev/null +++ b/.komment/komment.json @@ -0,0 +1,15 @@ +{ + "meta": { + "version": "1", + "updated_at": "2024-08-06T02:44:48.655Z", + "created_at": "2024-08-06T02:44:49.925Z", + "pipelines": [ + "b6ae3d16-3a08-4a94-a92c-72af0a5a0a40" + ] + }, + "lookup": [ + [ + "packages/listener/src/flatfile.listener.ts" + ] + ] +} \ No newline at end of file diff --git a/apps/react/app/App.tsx b/apps/react/app/App.tsx index 032aff9e..9187bc1e 100644 --- a/apps/react/app/App.tsx +++ b/apps/react/app/App.tsx @@ -3,7 +3,6 @@ import { document } from '@/utils/document' import { workbook } from '@/utils/workbook' import { recordHook } from '@flatfile/plugin-record-hook' import { - attachStyleSheet, Document, Sheet, Space, @@ -16,11 +15,20 @@ import { import { useEffect, useState } from 'react' import styles from './page.module.css' -attachStyleSheet({ nonce: 'flatfile-abc123' }) // add custom nonce - +/** + * @description Generates high-quality documentation for given code by using different + * listeners and plugins to log events and handle submissions, and by creating a + * portal iFrame window that can be opened or closed. + * + * @returns {Component} a React component that renders a portal and various listeners + * for event handling. + */ const App = () => { const { open, openPortal, closePortal } = useFlatfile() const [label, setLabel] = useState('Rock') + /** + * @description Either opens or closes a portal based on the provided `open` state. + */ const toggleOpen = () => { open ? closePortal({ reset: false }) : openPortal() } @@ -98,6 +106,27 @@ const App = () => { }} > + {/** + * @description Generates high-quality documentation for code given to it, including + * information on sheets submitted or recorded hooks. + * + * @param {object} config - Workbook configuration object, which defines various + * properties of the Workbook such as its name, onSubmit event handler, and record + * hooks for each sheet. + * + * @param {`AsyncFunction`.} onSubmit - 2nd sheet's onSubmit callback, which logs + * information to the console when called. + * + * * `onSubmit`: This function takes an argument called `sheet` which is an instance + * of the `Sheet` class. + * * `async`: This indicates that the function returns a promise. + * * `{ console.log('onWorkbookSubmission', sheet ) }`: This line logs a message to + * the console with the `sheet` object as its argument whenever the `onSubmit` function + * is called. + * + * @param {object} onRecordHooks - 2-element array of hook functions that will be + * called for each record when the Sheet is submitted or updated. + */} { ], ]} > + {/** + * @description Generates high-quality documentation for code given to it. In this + * case, it creates a new sheet with a name and slug specified, sets an onRecordHook + * to modify record data, and an onSubmit hook to log the submitted sheet information + * to the console. + * + * @param {object} config - configuration for a specific sheet, which includes setting + * the sheet name and overriding certain properties of the `workbook` object. + * + * @param {Anonymous Function.} onRecordHook - 1-time function that gets executed + * after each record is transformed into an Immutable record, resulting in an updated + * Immutable record with modified email property set to 'SHEET 3 RECORDHOOK'. + * + * * `record`: The recorded data in the sheet. It is an object with the following + * structure: `record => { email: string }`. + * * `sheet`: The `Sheet` instance itself, which contains additional metadata and + * configuration options for the sheet. + * + * @param {asynchronous function.} onSubmit - occurrence of a user submitting information + * through the Sheet 3 form, and when it is triggered, it logs an information message + * containing the sheet's data to the console. + * + * * `onSubmit`: A function that gets called when the sheet is submitted. The function + * takes the updated sheet as an argument (`{sheet}`) in the shape of an object + * containing the latest values for each record. + */} { console.log('onSubmit from Sheet 3', { sheet }) }} /> + {/** + * @description Sets up a new Google Sheets spreadsheet with a custom slug, name, and + * hooks for records and submissions. + * + * @param {object} config - configuration for the generated documentation, including + * the slug and name of the new sheet, as well as specifying the hook function for + * recording and submitting records. + * + * @param {Anonymous Function.} onRecordHook - function to execute on each record + * when it is hooked, and in this case, the function modifies the `email` field of + * the record by adding the string " SHEET 4 RECORDHOOK". + * + * * `record`: The updated record that is being hooked on to after being serialized + * and sent to the server for processing. Its value is a ` Record `. + * * `set(key: string, value: any)`: A function that updates the specified property + * of the record with the provided value. The keys are assumed to be valid string + * identifiers of properties in a JSON object. + * + * @param {object} onSubmit - sheet that is submitted after a record has been modified + * in the specified hook. + */} ` is an React component that provides the Flatfile provider + * for the App component. + * * `publishableKey` is a prop passed to the FlatfileProvider, which contains the + * publishable key used to sign the generated Flatfile. + * * `config` is another prop passed to the FlatfileProvider, which contains an + * object with two properties: `preload` and `styleSheetOptions`. The `preload` + * property sets whether the component should preload the Flatfile at runtime, while + * the `styleSheetOptions` property specifies a nonce value for the Flatfile. + */ export default function Home() { const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_FLATFILE_PUBLISHABLE_KEY if (!PUBLISHABLE_KEY) return <>No Publishable Key Available @@ -11,7 +27,8 @@ export default function Home() { diff --git a/packages/listener/src/flatfile.listener.ts b/packages/listener/src/flatfile.listener.ts index 96cfd561..f93f73cb 100644 --- a/packages/listener/src/flatfile.listener.ts +++ b/packages/listener/src/flatfile.listener.ts @@ -31,22 +31,37 @@ import { EventFilter, EventHandler } from './events' import { EventDriver } from './event-drivers' +/** + * @description Enables subscribing to events within a specific namespace and provides + * methods for filtering, creating, mounting, and unmounting event listeners using + * an Event Driver. It facilitates the handling of events by providing a flexible and + * reusable event listener infrastructure. + * + * @extends {EventHandler} + */ export class FlatfileListener extends EventHandler { /** - * Subscribe to events only within a certain namespace. - * - * @param namespace - * @param cb + * @description Filters an array-like object using a callback function and returns + * the result, passing two parameters: an array of strings representing namespaces + * and an optional callback function. + * + * @param {string | string[]} namespaces - Used for filtering purposes. + * + * @returns {Array} A filtered array of objects based on the given `namespaces` + * and callback function `cb`. */ namespace(namespaces: string | string[], cb?: SubFn) { return this.filter({ namespaces }, cb) } /** - * Filter by namespace - * - * @param filter - * @param cb + * @description Creates an instance of the same class with a given `EventFilter`, + * adds it as a node, and optionally calls a callback function with the created node + * as an argument. The method returns the created client instance. + * + * @param {EventFilter} filter - Used to specify filtering criteria. + * + * @returns {this} An instance of the class that contains the method. */ filter(filter: EventFilter, cb?: SubFn): this { const client = new (this.constructor as any)(filter) @@ -56,9 +71,14 @@ export class FlatfileListener extends EventHandler { } /** - * Start subscribing to events - * - * @param cb + * @description Generates an instance of itself, calls a provided callback function + * with this instance as argument, and returns the instance. The type parameter `T` + * ensures that the method can only be called on constructors of types that extend `FlatfileListener`. + * + * @param {SubFn} cb - Callback function. + * + * @returns {T} A constructor of FlatfileListener that has been initialized by calling + * the callback function with it as an argument. */ public static create( this: Constructor, @@ -70,7 +90,14 @@ export class FlatfileListener extends EventHandler { } /** - * Mount this client using an acceptable Event Driver + * @description Mounts an event handler for the provided `driver`. It binds the current + * object (`this`) to the driver's event handling mechanism, allowing it to receive + * and process events from the driver. The method returns the modified instance of `FlatfileListener`. + * + * @param {EventDriver} driver - Intended to provide event handling capabilities. + * + * @returns {this} An instance of the current class. The exact nature and purpose of + * this object are not specified within the provided code snippet. */ mount(driver: EventDriver) { driver.mountEventHandler(this) @@ -78,13 +105,26 @@ export class FlatfileListener extends EventHandler { } /** - * Unmount this client from the Event Driver + * @description Unregisters an event handler from the underlying `EventDriver`. It + * removes the reference to the listener and returns the instance itself for further + * method chaining. + * + * @param {EventDriver} driver - Intended to unmount an event handler. + * + * @returns {this} A reference to the object on which the function was called. */ unmount(driver: EventDriver) { driver.unmountEventHandler(this) return this } + /** + * @description Returns a new instance of `FlatfileListener`. This allows for the + * creation of multiple instances of the same listener, which can be used to handle + * different tasks or events independently. + * + * @returns {object} An instance of `FlatfileListener`. + */ fork() { return new FlatfileListener() } diff --git a/packages/react/rollup.config.js b/packages/react/rollup.config.js index 821c6edc..ecf2c65a 100644 --- a/packages/react/rollup.config.js +++ b/packages/react/rollup.config.js @@ -18,6 +18,20 @@ if (!PROD) { console.log('Not in production mode - skipping minification') } +/** + * @description Returns an array of plugins to be used in a Webpack configuration + * file for transpiling and bundling JavaScript and CSS code. It includes peer + * dependencies, JSON, CSS, CommonJS, ES modules, resolved dependencies, JSX + * transformation, and post-processing through Terser and PostCSS. + * + * @param {boolean} browser - browser environment and controls the behavior of other + * plugins in the `commonPlugins` function, including whether or not to include + * external dependencies and how to transform files. + * + * @param {false} umd - Boolean value of whether to include or exclude UMD plugins. + * + * @returns {array} an array of plugins to be used for bundling code in a browser environment. + */ function commonPlugins(browser, umd = false) { return [ umd @@ -73,6 +87,20 @@ const config = [ }, ], plugins: commonPlugins(false, false), + /** + * @description Skips certain warnings based on their code values, while console + * warning other warnings with the given message. + * + * @param {object} warning - warning to be skipped or warned, which can be either + * 'THIS_IS_UNDEFINED' or any other value for non-ignored warnings. + * + * @param {object} warn - warning to be displayed to the user. + * + * @returns {void} a warning message for any code that is not defined as `THIS_IS_UNDEFINED`. + * + * * `code`: The warning code that triggered the warning message. + * * `message`: The text message displayed in the console for the warning. + */ onwarn: function (warning, warn) { // Skip certain warnings if (warning.code === 'THIS_IS_UNDEFINED') { @@ -95,6 +123,27 @@ const config = [ }, ], plugins: commonPlugins(true, false), + /** + * @description Skips certain warnings based on a specified code and issues a warning + * message to the console for all other warnings. + * + * @param {object} warning - warning message that is to be displayed, and it is + * processed by the function accordingly. + * + * @param {object} warn - warning message that is to be output via the console. + * + * @returns {undefined value because the `if` condition evaluates to `true`, causing + * the function's second expression (i.e., `warn`) to be executed but with no value + * provided as an argument, resulting in an undefined output} a warning message for + * all warnings that are not related to the `THIS_IS_UNDEFINED` code. + * + * * `code`: A string that represents the warning code. (Example: `'THIS_IS_UNDEFINED'`) + * * `message`: A string that represents the message of the warning. (Example: `'This + * variable is undefined'')` + * * `object`: An object that contains additional properties related to the warning, + * such as the file and line number where the warning occurred. (Example: `{ file: + * 'main.js', line: 12 })` + */ onwarn: function (warning, warn) { // Skip certain warnings if (warning.code === 'THIS_IS_UNDEFINED') { @@ -116,6 +165,23 @@ const config = [ strict: true, }, plugins: commonPlugins(true, true), + /** + * @description Skips certain warnings and logs others to the console using `console.warn()`. + * + * @param {object} warning - warning message to be displayed, which the function + * either skips or displays in the console depending on its `code` property value. + * + * @param {object} warn - warning message to be logged to the console if it is not + * skipped based on the condition set in the code. + * + * @returns {error} a warning message for all warnings not specifically skipped. + * + * * `code`: The type of warning generated, which can be one of several predefined + * constants (e.g., 'THIS_IS_UNDEFINED', 'PATH_IS_NOT_ALLOWED', etc.). + * * `message`: A string representing the text message to be warned about. + * * `stack`: An optional string representing the stack trace associated with the + * warning, which can be used for debugging purposes. + */ onwarn: function (warning, warn) { // Skip certain warnings if (warning.code === 'THIS_IS_UNDEFINED') { diff --git a/packages/react/src/components/ConfirmCloseModal.tsx b/packages/react/src/components/ConfirmCloseModal.tsx index 501adc8f..3ad4a68d 100644 --- a/packages/react/src/components/ConfirmCloseModal.tsx +++ b/packages/react/src/components/ConfirmCloseModal.tsx @@ -1,5 +1,53 @@ import React from 'react' +/** + * @description Creates a modal component that displays an exit message and provides + * two buttons: one for canceling and one for confirming the exit. When a button is + * clicked, the `onClick` event handler is triggered, and the functionality of the + * button is executed. + * + * @param {() => void} .onConfirm - function to be executed when the user confirms + * the exit action. + * + * @param {() => void} .onCancel - function to be executed when the cancel button is + * clicked inside the modal window. + * + * @param {string} .exitText - text to be displayed in the modal's body for confirmation + * before closing the modal. + * + * @param {string} .exitTitle - title displayed above the modal when it is dismissed, + * typically providing a concise and informative description of the action being + * confirmed or cancelled. + * + * @param {string} .exitPrimaryButtonText - text to display on the primary button of + * the close confirmation modal, which is typically labeled as "OK" or "Save Changes". + * + * @param {string} .exitSecondaryButtonText - text to be displayed inside the secondary + * button that is located within the close confirm modal. + * + * @returns {HTMLDivElement} a modal component with a heading, text, primary and + * secondary buttons. + * + * * `onConfirm`: A function that will be called when the primary button is clicked. + * * `onCancel`: A function that will be called when the secondary button is clicked + * or when the user cancels the modal. + * * `exitText`: The text to display in the modal for the exit message. + * * `exitTitle`: The title to display in the modal for the exit message. + * * `exitPrimaryButtonText`: The text to display on the primary button in the modal. + * * `exitSecondaryButtonText`: The text to display on the secondary button in the + * modal. + * + * The returned output is a JSX element with a `div` container that contains the + * modal layout. The `div` element with the class `flatfile_outer-shell` contains the + * outer layer of the modal, while the `div` element with the class + * `flatfile_close-confirm-modal-inner` contains the inner layout of the modal. Inside + * the inner layout, there are three elements: a heading with the class + * `flatfile_modal-heading`, some text with the class `flatfile_modal-text`, and a + * button group containing two buttons with the classes `flatfile_button` and + * `flatfile_secondary`. The `onCancel` function is triggered when the secondary + * button is clicked or when the user cancels the modal, while the `onConfirm` function + * is triggered when the primary button is clicked. + */ export const ConfirmCloseModal = ({ onConfirm, onCancel, diff --git a/packages/react/src/components/FlatfileProvider.tsx b/packages/react/src/components/FlatfileProvider.tsx index ca4a88aa..5f1cd8ca 100644 --- a/packages/react/src/components/FlatfileProvider.tsx +++ b/packages/react/src/components/FlatfileProvider.tsx @@ -19,6 +19,8 @@ import { getSpace } from '../utils/getSpace' import { EmbeddedIFrameWrapper } from './EmbeddedIFrameWrapper' import FlatfileContext, { DEFAULT_CREATE_SPACE } from './FlatfileContext' +import { attachStyleSheet } from '../utils/attachStyleSheet' + const configDefaults: IFrameTypes = { preload: true, resetOnClose: true, @@ -31,6 +33,39 @@ interface ISessionSpace upgradedAt: string } +/** + * @description Providers Flatfile-related context and utilities to its child components: + * + * 1/ Handles opening a portal using `openPortal()` and creating/updating a space + * when `ready` is true. + * 2/ Manages the creation, updates, and removal of sheets, workbooks, documents, + * spaces, and instances. + * 3/ Triggers `handleCreateSpace`, `handleReUseSpace`, or `resetSpace` on readiness. + * + * @param {Component} .children - components or functionalities that are to be wrapped + * by the Flatfile provider and can be any JSX elements, function calls, or other + * React components. + * + * @param {string} .publishableKey - 16-character ID of the portal provider, which + * is required to authenticate and interact with the Flatfile platform. + * + * @param {string} .accessToken - 3D Flatfile provider's internal access token, which + * is used to authenticate and authorize API requests made by the component's `Provider` + * children. + * + * @param {string} .environmentId - Flatfile environment ID, which is used to identify + * and authenticate with the Flatfile service. + * + * @param {string} .apiUrl - API endpoint of Flatfile provider, which is used to fetch + * the data and perform operations within the platform. + * + * @param {object} .config - Flatfile provider configuration object that provides + * various properties and methods to manipulate the Flatfile workspace, sheets, books, + * and other state related information. + * + * @returns {object} a Flatfile provider context value that contains necessary data + * for Flatfile's functionality. + */ export const FlatfileProvider: React.FC = ({ children, publishableKey, @@ -73,6 +108,13 @@ export const FlatfileProvider: React.FC = ({ }, []) const [ready, setReady] = useState(false) + /** + * @description Automatically configures a space based on input parameters and sets + * internal access token and session space. + * + * @returns {object} an updated space object containing an access token for internal + * Flatfile API usage and the previous default page. + */ const handleCreateSpace = async () => { if (!publishableKey) { return @@ -98,6 +140,10 @@ export const FlatfileProvider: React.FC = ({ setSessionSpace(createdSpace) } + /** + * @description Updates the internal access token and session space based on provided + * information. + */ const handleReUseSpace = async () => { if (internalAccessToken && createSpace.space.id) { const { data: reUsedSpace } = await getSpace({ @@ -114,6 +160,27 @@ export const FlatfileProvider: React.FC = ({ } } + /** + * @description Updates an existing flatfile workbook by adding a new sheet to its + * sheets array if it does not already exist in the workbook, or returns the previous + * space with the updated workbook and sheets array if the sheet already exists. + * + * @param {Flatfile.SheetConfig} newSheet - updated sheet configuration that is being + * merged into the existing workbook. + * + * @returns {Workbook} an updated version of the previous space, with the newly + * provided sheet added to the workbook. + * + * * `prevSpace`: The existing space in the flat file is updated by setting this + * property. It contains information about the previous workbook, including its sheets. + * * `workbook`: This property contains information about the entire workbook, which + * includes all the sheets after the addition of the new sheet. It is an array that + * holds the previously existing sheets and the newly added sheet. + * + * In summary, the `addSheet` function modifies the existing space in the flat file + * by updating its `prevSpace` property and adding a new sheet to the workbook's + * `sheets` array. + */ const addSheet = (newSheet: Flatfile.SheetConfig) => { setCreateSpace((prevSpace) => { // Check if the sheet already exists @@ -134,6 +201,35 @@ export const FlatfileProvider: React.FC = ({ }) } + /** + * @description Updates a single sheet in a Flatfile workbook based on a given + * `sheetSlug`. It takes a `Partial` update object and returns + * an updated workbook with the modified sheet. + * + * @param {string} sheetSlug - slug of the sheet for which updates are being made, + * and is used to filter and merge existing sheets with the updated configurations + * in the `sheetUpdates` object. + * + * @param {Partial} sheetUpdates - updates to be made to an + * existing sheet with the same slug as the one passed in the `sheetSlug` parameter, + * by merging the original sheet's properties with the new ones. + * + * @returns {Flatfile.Workbook} a modified `Worksheet` object containing the updates + * to the specified sheet. + * + * * `prevSpace`: The previous space in the flat file is updated by setting this + * property. It has the shape of `Flatfile.Workspace`, which includes properties like + * `workbook` and `sheets`. + * * `workbook`: The workbook is an object that contains the shape of `Flatfile.Workbook`. + * It includes properties like `name`, `version`, `size`, `createdAt`, and `updatedAt`. + * * `sheets`: An array of objects, each representing a sheet in the flat file. Each + * object has the shape of `Flatfile.SheetConfig` and includes properties like `slug`, + * `name`, `type`, `rows`, `columns`, `cells`, and `annotations`. + * + * In summary, the `updateSheet` function updates the existing sheet in a flat file + * by taking its slug as input and returning an updated workspace object with the + * modified sheet information. + */ const updateSheet = ( sheetSlug: string, sheetUpdates: Partial @@ -156,6 +252,13 @@ export const FlatfileProvider: React.FC = ({ }) } + /** + * @description Updates a existing workbook configuration by applying new changes and + * prioritizing them over existing ones, then returns the updated workbook configuration. + * + * @param {Flatfile.CreateWorkbookConfig} workbookUpdates - updates to be applied to + * the workbook configuration, including changes to the workbook's sheets and actions. + */ const updateWorkbook = (workbookUpdates: Flatfile.CreateWorkbookConfig) => { setCreateSpace((prevSpace) => ({ ...prevSpace, @@ -175,6 +278,14 @@ export const FlatfileProvider: React.FC = ({ })) } + /** + * @description Updates an existing document by merging the provided `documentUpdates` + * with the previous document's state and creating a new one. + * + * @param {Flatfile.DocumentConfig} documentUpdates - updated document configuration + * for the flat file, which is merged with the existing document configuration in the + * `setCreateSpace` function to generate the final document update. + */ const updateDocument = (documentUpdates: Flatfile.DocumentConfig) => { setCreateSpace((prevSpace) => ({ ...prevSpace, @@ -185,6 +296,14 @@ export const FlatfileProvider: React.FC = ({ })) } + /** + * @description Updates an existing space within a Flatfile configuration by combining + * the previous space configuration with the given `spaceUpdates`. The resulting space + * configuration is then set as the new value for the `space` property. + * + * @param {Flatfile.SpaceConfig} spaceUpdates - updates to be applied to the existing + * space configuration. + */ const updateSpace = (spaceUpdates: Flatfile.SpaceConfig) => { setCreateSpace((prevSpace) => ({ ...prevSpace, @@ -192,6 +311,13 @@ export const FlatfileProvider: React.FC = ({ })) } + /** + * @description Sets `open` to `false`, resets the internal access token and session + * space, and preloads a Flatfile space if configured to do so. + * + * @param {ClosePortalOptions} .reset - Whether the internal access token and session + * space should be reset when closing the portal, which is done when set to `true`. + */ const resetSpace = ({ reset }: ClosePortalOptions = {}) => { setOpen(false) @@ -214,6 +340,14 @@ export const FlatfileProvider: React.FC = ({ // Works but only after the iframe is visible } } + const styleSheetRef = useRef(false) + + useEffect(() => { + if (!styleSheetRef.current) { + attachStyleSheet(config?.styleSheetOptions) + styleSheetRef.current = true + } + }, [config?.styleSheetOptions, styleSheetRef]) // Listen to the postMessage event from the created iFrame useEffect(() => { @@ -256,6 +390,12 @@ export const FlatfileProvider: React.FC = ({ // Triggers handleCreateSpace or handleReUseSpace when the openPortal() is clicked and ready is true useEffect(() => { if (ready && open) { + /** + * @description Determines whether to create a new space or update an existing one + * based on two input parameters: `publishableKey` and `internalAccessToken`. It calls + * the appropriate sub-function, `handleCreateSpace()` or `handleReUseSpace()`, + * depending on the input parameters. + */ const createOrUpdateSpace = async () => { if (publishableKey && !internalAccessToken) { await handleCreateSpace() diff --git a/packages/react/src/components/Spinner.tsx b/packages/react/src/components/Spinner.tsx index 12b146b8..efb47eb9 100644 --- a/packages/react/src/components/Spinner.tsx +++ b/packages/react/src/components/Spinner.tsx @@ -1,5 +1,19 @@ import React from 'react' +/** + * @description Renders an animated spinner icon with the given class name and test + * ID for use in React applications. + * + * @returns {HTMLDivElement} an HTML `
` element with a class of `spinner` and a + * data-testid of `"spinner-icon"`." + * + * * `className`: This is a string that represents the CSS class name for the spinner + * element. + * * `data-testid`: This is an attribute that assigns a unique identifier to the + * spinner element, allowing developers to easily identify and manipulate it in their + * code. + * * `
`: This is the HTML element that represents the spinner itself. + */ const Spinner = () => { return
} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index f3472fb5..65f1b06f 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -14,6 +14,15 @@ export * from './components' export * from './hooks' export type { ISidebarConfig, ISpace, ISpaceInfo, IThemeConfig, IUserInfo } +/** + * @description Inserts a CSS stylesheet into the page using the `styleInject` method, + * passing in the stylesheet and any optional parameters for insertion position and + * nonce. + * + * @param {object} options - settings for inserting the stylesheet at a particular + * location on the page and includes an optional nonce value used to verify the + * integrity of the stylesheet contents. + */ export function attachStyleSheet(options?: { insertAt?: 'top' nonce?: string diff --git a/packages/react/src/utils/attachStyleSheet.ts b/packages/react/src/utils/attachStyleSheet.ts new file mode 100644 index 00000000..8140f8da --- /dev/null +++ b/packages/react/src/utils/attachStyleSheet.ts @@ -0,0 +1,19 @@ +import { styleInject } from '../utils/styleInject' + +import stylesheet from '../components/style.scss' +export type StyleSheetOptions = { + insertAt?: 'top' + nonce?: string +} + +/** + * @description Attaches a CSS stylesheet to the current page or document using the + * `styleInject` method. + * + * @param {StyleSheetOptions} options - StyleSheetOptions object, which allows for + * customization of the sheet's behavior and styling, such as setting the sheet's ID + * or hiding specific rules. + */ +export function attachStyleSheet(options?: StyleSheetOptions) { + styleInject(stylesheet, options) +} diff --git a/packages/react/src/utils/styleInject.ts b/packages/react/src/utils/styleInject.ts index 98101e18..0c108e96 100644 --- a/packages/react/src/utils/styleInject.ts +++ b/packages/react/src/utils/styleInject.ts @@ -1,5 +1,26 @@ // adapted from https://github.com/egoist/style-inject +/** + * @description Creates a new `style` element and injects it into the Document Object + * Model (DOM) at either the beginning or end of the head section, based on the + * `insertAt` parameter. It also sets an optional `nonce` attribute to validate the + * styles. + * + * @param {string} css - CSS content that will be injected into the HTML document's + * head tag using the `styleInject` function. + * + * @param {'top'} .insertAt - location where the generated style rule should be + * inserted into the `` element of the HTML document, with `'top'` indicating + * insertion at the top of the `` element and any other value specifying an + * explicit position. + * + * @param {string} .nonce - nonce, which is an arbitrary value used to prevent caching + * of stylesheets and ensure they are reevaluated by the browser each time they are + * requested, helping protect against cross-site scripting (XSS) attacks. + * + * @returns {any} a newly created `