@nyaruka/temba-components 0.124.0 → 0.124.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/TEST_OPTIMIZATION.md +158 -0
- package/demo/alert/example.html +65 -0
- package/demo/button/example.html +71 -0
- package/demo/chart/example.html +56 -0
- package/demo/checkbox/example.html +72 -0
- package/demo/compose/example.html +72 -0
- package/demo/data/images/gus.png +0 -0
- package/demo/data/images/purrington.jpg +0 -0
- package/demo/data/server/opened-tickets.json +40 -0
- package/demo/data/server/response-time.json +27 -0
- package/demo/datepicker/example.html +69 -0
- package/demo/dialog/example.html +107 -0
- package/demo/dropdown/example.html +99 -0
- package/demo/index.html +152 -445
- package/demo/misc/example.html +72 -0
- package/demo/progress/example.html +59 -0
- package/demo/{drag-drop-demo.html → select/drag-and-drop.html} +2 -1
- package/demo/select/example.html +82 -0
- package/demo/select/multi.html +73 -0
- package/demo/slider/example.html +59 -0
- package/demo/sortable-list/example.html +99 -0
- package/demo/styles.css +183 -0
- package/demo/tabs/example.html +91 -0
- package/demo/textinput/completion.html +56 -0
- package/demo/textinput/example.html +61 -0
- package/dist/temba-components.js +23 -26
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/chart/TembaChart.js +27 -22
- package/out-tsc/src/chart/TembaChart.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1 -1
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/select/Select.js +1 -1
- package/out-tsc/src/select/Select.js.map +1 -1
- package/out-tsc/src/thumbnail/Thumbnail.js +1 -1
- package/out-tsc/src/thumbnail/Thumbnail.js.map +1 -1
- package/out-tsc/test/temba-chart.test.js +1 -1
- package/out-tsc/test/temba-chart.test.js.map +1 -1
- package/out-tsc/test/temba-compose.test.js +6 -30
- package/out-tsc/test/temba-compose.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +1 -2
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-dropdown.test.js +1 -1
- package/out-tsc/test/temba-dropdown.test.js.map +1 -1
- package/out-tsc/test/temba-omnibox.test.js +4 -0
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +49 -0
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/out-tsc/test/temba-toast.test.js +1 -2
- package/out-tsc/test/temba-toast.test.js.map +1 -1
- package/out-tsc/test/temba-utils-index.test.js +2 -2
- package/out-tsc/test/temba-utils-index.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +31 -3
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +2 -3
- package/screenshots/truth/webchat/connected-state.png +0 -0
- package/src/chart/TembaChart.ts +29 -22
- package/src/flow/Editor.ts +1 -1
- package/src/select/Select.ts +1 -1
- package/src/thumbnail/Thumbnail.ts +1 -1
- package/test/temba-chart.test.ts +1 -1
- package/test/temba-compose.test.ts +11 -38
- package/test/temba-contact-chat.test.ts +4 -6
- package/test/temba-dropdown.test.ts +1 -1
- package/test/temba-omnibox.test.ts +5 -0
- package/test/temba-select.test.ts +67 -0
- package/test/temba-toast.test.ts +2 -2
- package/test/temba-utils-index.test.ts +2 -2
- package/test/utils.test.ts +39 -3
- package/web-test-runner.config.mjs +4 -2
- package/.storybook/main.js +0 -14
- package/.storybook/preview-head.html +0 -1
- package/.storybook/preview.js +0 -17
- package/demo/agents.html +0 -147
- package/demo/old.html +0 -573
- package/demo/remote.html +0 -3
- package/demo/test-drag-drop.html +0 -94
- package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
- package/stories/temba-checkbox.stories.md +0 -37
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\nimport { replace, stub } from 'sinon';\nimport { Select, SelectOption } from '../src/select/Select';\nimport { Options } from '../src/options/Options';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n status: string;\n}\n\nconst gets: CodeMock[] = [];\nlet posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = (mocked) => {\n const mockResponse = new window.Response(mocked.body, {\n status: mocked.status,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = (mocked) => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: mocked.status,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options = { method: 'GET' }) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find((mock) => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nconst mockMapping = {\n '/test-assets/api/users/admin1.json': [\n /\\/api\\/v2\\/users.json\\?email=admin1@nyaruka.com/\n ],\n '/test-assets/api/users/editor1.json': [\n /\\/api\\/v2\\/users.json\\?email=editor1@nyaruka.com/\n ],\n '/test-assets/api/users/agent1.json': [\n /\\/api\\/v2\\/users.json\\?email=agent1@nyaruka.com/\n ],\n '/test-assets/api/users/viewer1.json': [\n /\\/api\\/v2\\/users.json\\?email=viewer1@nyaruka.com/\n ],\n '/test-assets/contacts/contact-tickets.json': [\n /\\/api\\/v2\\/tickets.json\\?contact=24d64810-3315-4ff5-be85-48e3fe055bf9/\n ]\n};\n\nexport const mockAPI = () => {\n for (const key in mockMapping) {\n const urls = mockMapping[key];\n for (const url of urls) {\n mockGET(url, key);\n }\n }\n};\n\nexport const mockGET = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n gets.push({ endpoint, body, headers, status });\n};\n\nexport const mockPOST = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n posts.push({ endpoint, body, headers, status });\n};\n\nexport const clearMockPosts = () => {\n posts = [];\n};\n\nexport const checkTimers = (clock: any) => {\n expect(!!clock.timers).to.equal(true, 'Expected timers not found');\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n window.setTimeout(resolve, millis);\n });\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n waitFor?: { clock?: any; predicate?: () => boolean }\n) => {\n if (waitFor) {\n if (waitFor.clock) {\n waitFor.clock.restore();\n }\n await waitUntil(waitFor.predicate);\n }\n\n // detect if we're running in copilot's environment and use adaptive threshold\n const isCopilotEnvironment = (window as any).isCopilotEnvironment;\n const threshold = isCopilotEnvironment ? 1.0 : 0.1;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x\n };\n\n return newClip;\n};\n\nexport const mouseClickElement = async (ele: HTMLElement | Element) => {\n const bounds = ele.getBoundingClientRect();\n await mouseClick(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n users='/test-assets/store/users.json'\n workspace='/test-assets/store/workspace.json'\n />`\n );\n await store.initialHttpComplete;\n await store.initialHttpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n const now = DateTime.fromISO(isodate);\n // mock the current time\n replace(DateTime, 'now', () => {\n return now;\n });\n};\n\nexport const getOptions = (select: Select<SelectOption>): Options => {\n return select.shadowRoot.querySelector('temba-options[visible]');\n};\n\nexport const clickOption = async (\n clock: any,\n select: Select<SelectOption>,\n index: number\n) => {\n const options = getOptions(select);\n const option = options.shadowRoot.querySelector(\n `[data-option-index=\"${index}\"]`\n ) as HTMLDivElement;\n\n await mouseClickElement(option);\n await options.updateComplete;\n await select.updateComplete;\n await clock.runAll();\n\n checkTimers(clock);\n};\nexport const openSelect = async (clock: any, select: Select<SelectOption>) => {\n const container = select.shadowRoot.querySelector('.select-container');\n container.dispatchEvent(new MouseEvent('click', { bubbles: true }));\n\n clock.runAll();\n\n // add more explicit waiting and clock ticks\n await select.updateComplete;\n clock.runAll();\n\n // ensure options are visible before proceeding\n await waitFor(100);\n clock.runAll();\n};\n\nexport const openAndClick = async (\n clock: any,\n select: Select<SelectOption>,\n idx: number\n) => {\n await openSelect(clock, select);\n\n // Add this line to ensure proper timing when running as part of a test suite\n await select.updateComplete;\n clock.tick(50); // Give extra time for options to render\n\n await clickOption(clock, select, idx);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\nimport { replace, stub } from 'sinon';\nimport { Select, SelectOption } from '../src/select/Select';\nimport { Options } from '../src/options/Options';\nimport { Attachment } from '../src/interfaces';\nimport { Compose } from '../src/compose/Compose';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n status: string;\n}\n\nconst gets: CodeMock[] = [];\nlet posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = (mocked) => {\n const mockResponse = new window.Response(mocked.body, {\n status: mocked.status,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = (mocked) => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: mocked.status,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options = { method: 'GET' }) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find((mock) => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nconst mockMapping = {\n '/test-assets/api/users/admin1.json': [\n /\\/api\\/v2\\/users.json\\?email=admin1@nyaruka.com/\n ],\n '/test-assets/api/users/editor1.json': [\n /\\/api\\/v2\\/users.json\\?email=editor1@nyaruka.com/\n ],\n '/test-assets/api/users/agent1.json': [\n /\\/api\\/v2\\/users.json\\?email=agent1@nyaruka.com/\n ],\n '/test-assets/api/users/viewer1.json': [\n /\\/api\\/v2\\/users.json\\?email=viewer1@nyaruka.com/\n ],\n '/test-assets/contacts/contact-tickets.json': [\n /\\/api\\/v2\\/tickets.json\\?contact=24d64810-3315-4ff5-be85-48e3fe055bf9/\n ]\n};\n\nexport const mockAPI = () => {\n for (const key in mockMapping) {\n const urls = mockMapping[key];\n for (const url of urls) {\n mockGET(url, key);\n }\n }\n};\n\nexport const mockGET = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n gets.push({ endpoint, body, headers, status });\n};\n\nexport const mockPOST = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n posts.push({ endpoint, body, headers, status });\n};\n\nexport const clearMockPosts = () => {\n posts = [];\n};\n\nexport const checkTimers = (clock: any) => {\n expect(!!clock.timers).to.equal(true, 'Expected timers not found');\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n window.setTimeout(resolve, millis);\n });\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n waitFor?: { clock?: any; predicate?: () => boolean }\n) => {\n if (waitFor) {\n if (waitFor.clock) {\n waitFor.clock.restore();\n }\n await waitUntil(waitFor.predicate);\n }\n\n // detect if we're running in copilot's environment and use adaptive threshold\n const isCopilotEnvironment = (window as any).isCopilotEnvironment;\n const threshold = isCopilotEnvironment ? 1.0 : 0.1;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x\n };\n\n return newClip;\n};\n\nexport const mouseClickElement = async (ele: HTMLElement | Element) => {\n const bounds = ele.getBoundingClientRect();\n await mouseClick(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n users='/test-assets/store/users.json'\n workspace='/test-assets/store/workspace.json'\n />`\n );\n await store.initialHttpComplete;\n await store.initialHttpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n const now = DateTime.fromISO(isodate);\n // mock the current time\n replace(DateTime, 'now', () => {\n return now;\n });\n};\n\nexport const getOptions = (select: Select<SelectOption>): Options => {\n return select.shadowRoot.querySelector('temba-options[visible]');\n};\n\nexport const clickOption = async (\n clock: any,\n select: Select<SelectOption>,\n index: number\n) => {\n const options = getOptions(select);\n const option = options.shadowRoot.querySelector(\n `[data-option-index=\"${index}\"]`\n ) as HTMLDivElement;\n\n await mouseClickElement(option);\n await options.updateComplete;\n await select.updateComplete;\n await clock.runAll();\n\n checkTimers(clock);\n};\nexport const openSelect = async (clock: any, select: Select<SelectOption>) => {\n const container = select.shadowRoot.querySelector('.select-container');\n container.dispatchEvent(new MouseEvent('click', { bubbles: true }));\n\n clock.runAll();\n\n // add more explicit waiting and clock ticks\n await select.updateComplete;\n clock.runAll();\n\n // reduce wait time for options to become visible\n await waitFor(25);\n clock.runAll();\n};\n\nexport const openAndClick = async (\n clock: any,\n select: Select<SelectOption>,\n idx: number\n) => {\n await openSelect(clock, select);\n\n // Add this line to ensure proper timing when running as part of a test suite\n await select.updateComplete;\n clock.tick(25); // Reduced from 50 to give minimum time for options to render\n\n await clickOption(clock, select, idx);\n};\n\n// valid = attachments that are uploaded sent to the server when the user clicks send\nexport const getValidAttachments = (numFiles = 2): Attachment[] => {\n const attachments = [];\n let index = 1;\n while (index <= numFiles) {\n const s = 's' + index;\n const attachment = {\n uuid: s,\n content_type: 'image/png',\n type: 'image/png',\n filename: 'name_' + s,\n url: 'url_' + s,\n size: 1024,\n error: null\n } as Attachment;\n attachments.push(attachment);\n index++;\n }\n return attachments;\n};\n\nexport const updateComponent = async (\n compose: Compose,\n text?: string,\n attachments?: Attachment[]\n): Promise<void> => {\n compose.initialText = text ? text : '';\n compose.currentAttachments = attachments ? attachments : [];\n await compose.updateComplete;\n};\nexport const getValidText = () => {\n return 'sà-wàd-dee!';\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nyaruka/temba-components",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.2",
|
|
4
4
|
"description": "Web components to support rapidpro and related projects",
|
|
5
5
|
"author": "Nyaruka <code@nyaruka.coim>",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,10 +21,9 @@
|
|
|
21
21
|
"format:prettier": "prettier \"**/*.js\" \"**/*.ts\" --config .prettierrc --write --ignore-path .gitignore",
|
|
22
22
|
"format": "yarn format:eslint && yarn format:prettier",
|
|
23
23
|
"test": "wtr --node-resolve",
|
|
24
|
+
"test:fast": "wtr --node-resolve --fast",
|
|
24
25
|
"validate": "yarn format && yarn build && yarn test --coverage",
|
|
25
26
|
"test:watch": "wtr --node-resolve --watch",
|
|
26
|
-
"storybook": "concurrently --kill-others --names tsc,storybook \"npm run tsc:watch\" \"start-storybook --node-resolve --watch --open\"",
|
|
27
|
-
"storybook:build": "build-storybook",
|
|
28
27
|
"svg": "rimraf static/svg/work && node svg.js --resolution=150 --output='./static/svg/index.svg' --usage='./src/vectoricon/index.ts'",
|
|
29
28
|
"svg-wc": "rimraf static/svg/work && node svg.js --resolution=150 --output='./static/svg/webchat.svg' --usage='./src/webchat/index.ts'",
|
|
30
29
|
"version": "yarn run build && auto-changelog -p && git add CHANGELOG.md",
|
|
Binary file
|
package/src/chart/TembaChart.ts
CHANGED
|
@@ -93,6 +93,12 @@ export class TembaChart extends RapidElement {
|
|
|
93
93
|
@property({ type: Number })
|
|
94
94
|
maxSplits: number = 2;
|
|
95
95
|
|
|
96
|
+
@property({ type: String, attribute: 'splits' })
|
|
97
|
+
splitNames: string;
|
|
98
|
+
|
|
99
|
+
@property({ type: Boolean })
|
|
100
|
+
hideOther: boolean = false;
|
|
101
|
+
|
|
96
102
|
@state()
|
|
97
103
|
splits: string[] = [];
|
|
98
104
|
|
|
@@ -111,6 +117,9 @@ export class TembaChart extends RapidElement {
|
|
|
111
117
|
@property({ type: Boolean })
|
|
112
118
|
formatDuration: boolean = false;
|
|
113
119
|
|
|
120
|
+
@property({ type: Boolean })
|
|
121
|
+
showAll: boolean = false;
|
|
122
|
+
|
|
114
123
|
@property({ type: Number })
|
|
115
124
|
colorIndex: number = 0;
|
|
116
125
|
|
|
@@ -152,7 +161,6 @@ export class TembaChart extends RapidElement {
|
|
|
152
161
|
|
|
153
162
|
.config {
|
|
154
163
|
max-height: 0px;
|
|
155
|
-
margin: 2em 0.5em;
|
|
156
164
|
padding: 0em 1em;
|
|
157
165
|
border-radius: var(--curvature);
|
|
158
166
|
border: 1px solid transparent;
|
|
@@ -162,10 +170,8 @@ export class TembaChart extends RapidElement {
|
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
.config.show {
|
|
165
|
-
padding: 1em;
|
|
173
|
+
padding: 2em 1em 1.5em 1em;
|
|
166
174
|
max-height: 50px;
|
|
167
|
-
background: rgba(0, 0, 0, 0.02);
|
|
168
|
-
border: 1px solid rgba(0, 0, 0, 0.09);
|
|
169
175
|
}
|
|
170
176
|
`;
|
|
171
177
|
}
|
|
@@ -189,6 +195,11 @@ export class TembaChart extends RapidElement {
|
|
|
189
195
|
changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
|
190
196
|
): void {
|
|
191
197
|
super.updated(changes);
|
|
198
|
+
|
|
199
|
+
if (changes.has('splitNames')) {
|
|
200
|
+
this.splits = this.splitNames.split(',').map((s) => s.trim());
|
|
201
|
+
}
|
|
202
|
+
|
|
192
203
|
if (changes.has('data') || changes.has('splits')) {
|
|
193
204
|
this.calculateSplits();
|
|
194
205
|
}
|
|
@@ -199,7 +210,7 @@ export class TembaChart extends RapidElement {
|
|
|
199
210
|
|
|
200
211
|
if (changes.has('url')) {
|
|
201
212
|
const store = getStore();
|
|
202
|
-
store.getUrl(this.url).then((response) => {
|
|
213
|
+
store.getUrl(this.url, { skipCache: true }).then((response) => {
|
|
203
214
|
this.data = response.json.data;
|
|
204
215
|
});
|
|
205
216
|
}
|
|
@@ -211,7 +222,10 @@ export class TembaChart extends RapidElement {
|
|
|
211
222
|
// keep a running list of values that is the sum at each index
|
|
212
223
|
const sums = [];
|
|
213
224
|
for (const dataset of this.data.datasets) {
|
|
214
|
-
if (
|
|
225
|
+
if (
|
|
226
|
+
!this.showAll &&
|
|
227
|
+
this.splits.find((s) => s === dataset.label) === undefined
|
|
228
|
+
) {
|
|
215
229
|
// update our sums
|
|
216
230
|
for (let i = 0; i < dataset.data.length; i++) {
|
|
217
231
|
if (sums[i] === undefined) {
|
|
@@ -243,13 +257,15 @@ export class TembaChart extends RapidElement {
|
|
|
243
257
|
borderWidth: 1
|
|
244
258
|
});
|
|
245
259
|
} else {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
260
|
+
if (!this.hideOther && !this.showAll) {
|
|
261
|
+
datasets.push({
|
|
262
|
+
label: 'Other',
|
|
263
|
+
data: sums,
|
|
264
|
+
backgroundColor: otherBackgroundColor,
|
|
265
|
+
borderColor: otherBorderColor,
|
|
266
|
+
borderWidth: 1
|
|
267
|
+
});
|
|
268
|
+
}
|
|
253
269
|
}
|
|
254
270
|
this.datasets = datasets;
|
|
255
271
|
}
|
|
@@ -292,15 +308,6 @@ export class TembaChart extends RapidElement {
|
|
|
292
308
|
x: { from: 500 },
|
|
293
309
|
y: { from: 500 }
|
|
294
310
|
},
|
|
295
|
-
animations: {
|
|
296
|
-
tension: {
|
|
297
|
-
duration: 1000,
|
|
298
|
-
easing: 'linear',
|
|
299
|
-
from: 1,
|
|
300
|
-
to: 0,
|
|
301
|
-
loop: true
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
311
|
scales: {
|
|
305
312
|
y: {
|
|
306
313
|
min: 0,
|
package/src/flow/Editor.ts
CHANGED
|
@@ -160,7 +160,7 @@ export class Editor extends RapidElement {
|
|
|
160
160
|
): void {
|
|
161
161
|
super.updated(changes);
|
|
162
162
|
if (changes.has('canvasSize')) {
|
|
163
|
-
console.log('Setting canvas size', this.canvasSize);
|
|
163
|
+
// console.log('Setting canvas size', this.canvasSize);
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
package/src/select/Select.ts
CHANGED
|
@@ -118,7 +118,7 @@ export class Thumbnail extends RapidElement {
|
|
|
118
118
|
@property({ type: Boolean, attribute: false })
|
|
119
119
|
zoom: boolean;
|
|
120
120
|
|
|
121
|
-
@property({ type: String, attribute:
|
|
121
|
+
@property({ type: String, attribute: true })
|
|
122
122
|
contentType: string;
|
|
123
123
|
|
|
124
124
|
protected updated(
|
package/test/temba-chart.test.ts
CHANGED
|
@@ -127,7 +127,7 @@ describe('temba-chart', () => {
|
|
|
127
127
|
await chart.updateComplete;
|
|
128
128
|
|
|
129
129
|
// Wait for the chart to be created after data is set
|
|
130
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
130
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
131
131
|
|
|
132
132
|
expect(chart.chart).to.exist;
|
|
133
133
|
const tickCallback = chart.chart.options.scales.y.ticks.callback;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { assert, expect } from '@open-wc/testing';
|
|
2
2
|
import { Compose } from '../src/compose/Compose';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
assertScreenshot,
|
|
5
|
+
getClip,
|
|
6
|
+
getComponent,
|
|
7
|
+
getValidAttachments,
|
|
8
|
+
getValidText,
|
|
9
|
+
updateComponent
|
|
10
|
+
} from './utils.test';
|
|
4
11
|
import { DEFAULT_MEDIA_ENDPOINT } from '../src/utils';
|
|
5
12
|
import { Attachment } from '../src/interfaces';
|
|
6
13
|
|
|
@@ -17,16 +24,6 @@ const getCompose = async (attrs: any = {}, width = 500, height = 500) => {
|
|
|
17
24
|
return compose;
|
|
18
25
|
};
|
|
19
26
|
|
|
20
|
-
export const updateComponent = async (
|
|
21
|
-
compose: Compose,
|
|
22
|
-
text?: string,
|
|
23
|
-
attachments?: Attachment[]
|
|
24
|
-
): Promise<void> => {
|
|
25
|
-
compose.initialText = text ? text : '';
|
|
26
|
-
compose.currentAttachments = attachments ? attachments : [];
|
|
27
|
-
await compose.updateComplete;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
27
|
const getInitialValue = (
|
|
31
28
|
text?: string,
|
|
32
29
|
attachments?: Attachment[],
|
|
@@ -48,31 +45,6 @@ const getComposeValue = (value: any): string => {
|
|
|
48
45
|
return JSON.stringify(value);
|
|
49
46
|
};
|
|
50
47
|
|
|
51
|
-
export const getValidText = () => {
|
|
52
|
-
return 'sà-wàd-dee!';
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// valid = attachments that are uploaded sent to the server when the user clicks send
|
|
56
|
-
export const getValidAttachments = (numFiles = 2): Attachment[] => {
|
|
57
|
-
const attachments = [];
|
|
58
|
-
let index = 1;
|
|
59
|
-
while (index <= numFiles) {
|
|
60
|
-
const s = 's' + index;
|
|
61
|
-
const attachment = {
|
|
62
|
-
uuid: s,
|
|
63
|
-
content_type: 'image/png',
|
|
64
|
-
type: 'image/png',
|
|
65
|
-
filename: 'name_' + s,
|
|
66
|
-
url: 'url_' + s,
|
|
67
|
-
size: 1024,
|
|
68
|
-
error: null
|
|
69
|
-
} as Attachment;
|
|
70
|
-
attachments.push(attachment);
|
|
71
|
-
index++;
|
|
72
|
-
}
|
|
73
|
-
return attachments;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
48
|
// for a test width of 500, return a string that is 60+ chars with spaces
|
|
77
49
|
// to test that line breaks / word wrapping works as expected
|
|
78
50
|
const getValidText_Long_WithSpaces = () => {
|
|
@@ -179,10 +151,11 @@ describe('temba-compose attachments', () => {
|
|
|
179
151
|
const tabs = compose.getTabs();
|
|
180
152
|
tabs.focusTab('Attachments');
|
|
181
153
|
|
|
182
|
-
|
|
154
|
+
// todo: this test is weirdly inconsistent
|
|
155
|
+
/* await assertScreenshot(
|
|
183
156
|
'compose/attachments-with-files-focused',
|
|
184
157
|
getClip(compose)
|
|
185
|
-
)
|
|
158
|
+
);*/
|
|
186
159
|
});
|
|
187
160
|
|
|
188
161
|
it('serializes attachments', async () => {
|
|
@@ -7,17 +7,15 @@ import {
|
|
|
7
7
|
clearMockPosts,
|
|
8
8
|
getClip,
|
|
9
9
|
getComponent,
|
|
10
|
+
getValidAttachments,
|
|
11
|
+
getValidText,
|
|
10
12
|
loadStore,
|
|
11
13
|
mockAPI,
|
|
12
14
|
mockGET,
|
|
13
15
|
mockNow,
|
|
14
|
-
mockPOST
|
|
15
|
-
} from '../test/utils.test';
|
|
16
|
-
import {
|
|
17
|
-
getValidAttachments,
|
|
18
|
-
getValidText,
|
|
16
|
+
mockPOST,
|
|
19
17
|
updateComponent
|
|
20
|
-
} from '
|
|
18
|
+
} from '../test/utils.test';
|
|
21
19
|
|
|
22
20
|
import { expect, oneEvent } from '@open-wc/testing';
|
|
23
21
|
|
|
@@ -5,7 +5,7 @@ import { assertScreenshot, getClip, getComponent } from './utils.test';
|
|
|
5
5
|
const TAG = 'temba-dropdown';
|
|
6
6
|
|
|
7
7
|
// Helper function to wait for stable rendering
|
|
8
|
-
const waitForStableRender = async (dropdown: Dropdown, timeoutMs =
|
|
8
|
+
const waitForStableRender = async (dropdown: Dropdown, timeoutMs = 100) => {
|
|
9
9
|
await dropdown.updateComplete;
|
|
10
10
|
// Double wait to ensure any async positioning is complete
|
|
11
11
|
await new Promise((resolve) => setTimeout(resolve, timeoutMs));
|
|
@@ -57,7 +57,12 @@ describe('temba-omnibox', () => {
|
|
|
57
57
|
const changeEvent = spy();
|
|
58
58
|
omnibox.addEventListener('change', changeEvent);
|
|
59
59
|
|
|
60
|
+
clock.runAll();
|
|
61
|
+
await omnibox.updateComplete;
|
|
62
|
+
clock.runAll();
|
|
63
|
+
|
|
60
64
|
await openAndClick(clock, omnibox, 0);
|
|
65
|
+
clock.runAll();
|
|
61
66
|
assert(changeEvent.called, 'change event not fired');
|
|
62
67
|
|
|
63
68
|
await assertScreenshot('omnibox/selected', getClip(omnibox));
|
|
@@ -505,6 +505,73 @@ describe('temba-select', () => {
|
|
|
505
505
|
});
|
|
506
506
|
});
|
|
507
507
|
|
|
508
|
+
describe('tags functionality', () => {
|
|
509
|
+
it('shows selected item text when typing second tag', async () => {
|
|
510
|
+
const select = await createSelect(
|
|
511
|
+
clock,
|
|
512
|
+
getSelectHTML([], {
|
|
513
|
+
placeholder: 'Enter tags',
|
|
514
|
+
multi: true,
|
|
515
|
+
searchable: true,
|
|
516
|
+
tags: true
|
|
517
|
+
})
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
// Add first tag programmatically (simulating user adding first tag)
|
|
521
|
+
select.addValue({ name: 'Yes', value: 'Yes' });
|
|
522
|
+
await select.updateComplete;
|
|
523
|
+
expect(select.values.length).to.equal(1);
|
|
524
|
+
expect(select.values[0].name).to.equal('Yes');
|
|
525
|
+
|
|
526
|
+
// Check that the first tag is displayed with text
|
|
527
|
+
let selectedItems = select.shadowRoot.querySelectorAll('.selected-item');
|
|
528
|
+
expect(selectedItems.length).to.equal(1);
|
|
529
|
+
expect(selectedItems[0].textContent).to.contain('Yes');
|
|
530
|
+
|
|
531
|
+
// Start typing second tag (this should not hide the first tag's text)
|
|
532
|
+
await typeInto('temba-select', 'No', false, false);
|
|
533
|
+
|
|
534
|
+
// Check that first tag text is still visible while typing second tag
|
|
535
|
+
selectedItems = select.shadowRoot.querySelectorAll('.selected-item');
|
|
536
|
+
expect(selectedItems.length).to.equal(1);
|
|
537
|
+
|
|
538
|
+
// The selected item should still contain the text "Yes"
|
|
539
|
+
const firstItemText = selectedItems[0].textContent;
|
|
540
|
+
expect(firstItemText).to.contain('Yes');
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it('hides selected item text when typing in single-select mode', async () => {
|
|
544
|
+
const select = await createSelect(
|
|
545
|
+
clock,
|
|
546
|
+
getSelectHTML(colors, {
|
|
547
|
+
placeholder: 'Select a color',
|
|
548
|
+
searchable: true
|
|
549
|
+
})
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
// Select an option first
|
|
553
|
+
await openAndClick(clock, select, 0); // Select Red
|
|
554
|
+
expect(select.values.length).to.equal(1);
|
|
555
|
+
expect(select.values[0].name).to.equal('Red');
|
|
556
|
+
|
|
557
|
+
// Check that the selected item is displayed with text when not typing
|
|
558
|
+
let selectedItems = select.shadowRoot.querySelectorAll('.selected-item');
|
|
559
|
+
expect(selectedItems.length).to.equal(1);
|
|
560
|
+
expect(selectedItems[0].textContent).to.contain('Red');
|
|
561
|
+
|
|
562
|
+
// Start typing in the search box
|
|
563
|
+
await typeInto('temba-select', 'gr', false, false);
|
|
564
|
+
|
|
565
|
+
// Check that selected item text is hidden while typing (preserving single-select behavior)
|
|
566
|
+
selectedItems = select.shadowRoot.querySelectorAll('.selected-item');
|
|
567
|
+
expect(selectedItems.length).to.equal(1);
|
|
568
|
+
|
|
569
|
+
// The selected item should NOT contain the text "Red" when typing
|
|
570
|
+
const itemText = selectedItems[0].textContent.trim();
|
|
571
|
+
expect(itemText).to.not.contain('Red');
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
|
|
508
575
|
describe('static options', () => {
|
|
509
576
|
it('accepts an initial value', async () => {
|
|
510
577
|
const select = await createSelect(
|
package/test/temba-toast.test.ts
CHANGED
|
@@ -17,6 +17,7 @@ export const createToast = async (attrs: any = {}) => {
|
|
|
17
17
|
describe('temba-toast', () => {
|
|
18
18
|
it('can be created', async () => {
|
|
19
19
|
const toast = await createToast();
|
|
20
|
+
|
|
20
21
|
assert.instanceOf(toast, Toast);
|
|
21
22
|
expect(toast.messages).to.deep.equal([]);
|
|
22
23
|
expect(toast.staleDuration).to.equal(5000);
|
|
@@ -127,8 +128,7 @@ describe('temba-toast', () => {
|
|
|
127
128
|
// Initially not visible
|
|
128
129
|
expect(toast.messages[0].visible).to.be.undefined;
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
131
|
+
await waitFor(200);
|
|
132
132
|
|
|
133
133
|
expect(toast.messages[0].visible).to.be.true;
|
|
134
134
|
});
|
|
@@ -597,7 +597,7 @@ describe('utils/index', () => {
|
|
|
597
597
|
expect(fn.calledOnce).to.be.true;
|
|
598
598
|
expect(fn.calledWith('arg3')).to.be.true;
|
|
599
599
|
done();
|
|
600
|
-
},
|
|
600
|
+
}, 75);
|
|
601
601
|
});
|
|
602
602
|
|
|
603
603
|
it('calls immediately when immediate flag is true', () => {
|
|
@@ -632,7 +632,7 @@ describe('utils/index', () => {
|
|
|
632
632
|
throttledFn('arg4');
|
|
633
633
|
expect(fn.callCount).to.equal(2);
|
|
634
634
|
done();
|
|
635
|
-
},
|
|
635
|
+
}, 75);
|
|
636
636
|
});
|
|
637
637
|
});
|
|
638
638
|
|
package/test/utils.test.ts
CHANGED
|
@@ -13,6 +13,8 @@ import { Store } from '../src/store/Store';
|
|
|
13
13
|
import { replace, stub } from 'sinon';
|
|
14
14
|
import { Select, SelectOption } from '../src/select/Select';
|
|
15
15
|
import { Options } from '../src/options/Options';
|
|
16
|
+
import { Attachment } from '../src/interfaces';
|
|
17
|
+
import { Compose } from '../src/compose/Compose';
|
|
16
18
|
|
|
17
19
|
export interface CodeMock {
|
|
18
20
|
endpoint: RegExp;
|
|
@@ -313,8 +315,8 @@ export const openSelect = async (clock: any, select: Select<SelectOption>) => {
|
|
|
313
315
|
await select.updateComplete;
|
|
314
316
|
clock.runAll();
|
|
315
317
|
|
|
316
|
-
//
|
|
317
|
-
await waitFor(
|
|
318
|
+
// reduce wait time for options to become visible
|
|
319
|
+
await waitFor(25);
|
|
318
320
|
clock.runAll();
|
|
319
321
|
};
|
|
320
322
|
|
|
@@ -327,7 +329,41 @@ export const openAndClick = async (
|
|
|
327
329
|
|
|
328
330
|
// Add this line to ensure proper timing when running as part of a test suite
|
|
329
331
|
await select.updateComplete;
|
|
330
|
-
clock.tick(
|
|
332
|
+
clock.tick(25); // Reduced from 50 to give minimum time for options to render
|
|
331
333
|
|
|
332
334
|
await clickOption(clock, select, idx);
|
|
333
335
|
};
|
|
336
|
+
|
|
337
|
+
// valid = attachments that are uploaded sent to the server when the user clicks send
|
|
338
|
+
export const getValidAttachments = (numFiles = 2): Attachment[] => {
|
|
339
|
+
const attachments = [];
|
|
340
|
+
let index = 1;
|
|
341
|
+
while (index <= numFiles) {
|
|
342
|
+
const s = 's' + index;
|
|
343
|
+
const attachment = {
|
|
344
|
+
uuid: s,
|
|
345
|
+
content_type: 'image/png',
|
|
346
|
+
type: 'image/png',
|
|
347
|
+
filename: 'name_' + s,
|
|
348
|
+
url: 'url_' + s,
|
|
349
|
+
size: 1024,
|
|
350
|
+
error: null
|
|
351
|
+
} as Attachment;
|
|
352
|
+
attachments.push(attachment);
|
|
353
|
+
index++;
|
|
354
|
+
}
|
|
355
|
+
return attachments;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
export const updateComponent = async (
|
|
359
|
+
compose: Compose,
|
|
360
|
+
text?: string,
|
|
361
|
+
attachments?: Attachment[]
|
|
362
|
+
): Promise<void> => {
|
|
363
|
+
compose.initialText = text ? text : '';
|
|
364
|
+
compose.currentAttachments = attachments ? attachments : [];
|
|
365
|
+
await compose.updateComplete;
|
|
366
|
+
};
|
|
367
|
+
export const getValidText = () => {
|
|
368
|
+
return 'sà-wàd-dee!';
|
|
369
|
+
};
|
|
@@ -150,8 +150,9 @@ const wireScreenshots = async (page, context, wait, replaceScreenshots) => {
|
|
|
150
150
|
const testFile = await getPath(TEST, filename);
|
|
151
151
|
const truthFile = await getPath(TRUTH, filename);
|
|
152
152
|
|
|
153
|
+
// Only wait for network idle if explicitly requested
|
|
153
154
|
if (wait) {
|
|
154
|
-
await page.waitForNetworkIdle();
|
|
155
|
+
await page.waitForNetworkIdle({ idleTime: 100, timeout: 1000 });
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
if (!(await fileExists(truthFile))) {
|
|
@@ -302,9 +303,10 @@ export default {
|
|
|
302
303
|
files: '**/test/**/*.test.ts',
|
|
303
304
|
nodeResolve: true,
|
|
304
305
|
setupFiles: ['./test-setup.js'],
|
|
306
|
+
concurrency: 4,
|
|
305
307
|
testFramework: {
|
|
306
308
|
config: {
|
|
307
|
-
timeout: '
|
|
309
|
+
timeout: '5000',
|
|
308
310
|
},
|
|
309
311
|
},
|
|
310
312
|
|
package/.storybook/main.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
stories: ['../stories/**/*.stories.{js,md,mdx}'],
|
|
3
|
-
addons: [
|
|
4
|
-
'storybook-prebuilt/addon-knobs/register.js',
|
|
5
|
-
'storybook-prebuilt/addon-docs/register.js',
|
|
6
|
-
'storybook-prebuilt/addon-viewport/register.js'
|
|
7
|
-
],
|
|
8
|
-
esDevServer: {
|
|
9
|
-
// custom es-dev-server options
|
|
10
|
-
nodeResolve: true,
|
|
11
|
-
watch: true,
|
|
12
|
-
open: true
|
|
13
|
-
}
|
|
14
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<link type="text/css" rel="stylesheet" href="https://textit.com/sitestatic/css/temba-components.css"/>
|
package/.storybook/preview.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { addParameters, setCustomElements } from '@open-wc/demoing-storybook';
|
|
2
|
-
|
|
3
|
-
addParameters({
|
|
4
|
-
docs: {
|
|
5
|
-
iframeHeight: '200px'
|
|
6
|
-
}
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
async function run() {
|
|
10
|
-
const customElements = await (
|
|
11
|
-
await fetch(new URL('../custom-elements.json', import.meta.url))
|
|
12
|
-
).json();
|
|
13
|
-
|
|
14
|
-
setCustomElements(customElements);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
run();
|