├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── tests.yaml ├── .gitignore ├── .gitmodules ├── .storybook ├── main.js └── preview.js ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TESTING.md ├── app ├── README.md ├── __plugin__init__ │ ├── README.md │ └── index.ts ├── lib │ ├── app.css │ ├── app.css.d.ts │ ├── components │ │ ├── action-after-filekey-set-button.tsx │ │ ├── animated │ │ │ ├── index.ts │ │ │ └── reveal-when-visible.tsx │ │ ├── comming-soon-template.tsx │ │ ├── index.ts │ │ ├── motions │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── smooth-dampings │ │ │ │ └── index.ts │ │ │ └── update-hide-by-scroll-position-and-velocity │ │ │ │ └── index.ts │ │ ├── navigation │ │ │ ├── index.ts │ │ │ ├── navigation-motions.tsx │ │ │ ├── navigator-expansion-control-button.stories.mdx │ │ │ ├── navigator-expansion-control-button.tsx │ │ │ ├── primary-workmode-select.stories.mdx │ │ │ ├── primary-workmode-select.tsx │ │ │ ├── route-back-button.tsx │ │ │ ├── secondary-menu-dropdown.tsx │ │ │ ├── secondary-workmode-choice.tsx │ │ │ ├── secondary-workmode-menu.tsx │ │ │ ├── work-mode-button.tsx │ │ │ └── workmode-screen-tabs.tsx │ │ ├── open-in-editor-button.tsx │ │ ├── storybook-screen.tsx │ │ └── ui.css │ ├── index.ts │ ├── main │ │ ├── global-state-atoms.ts │ │ └── index.tsx │ ├── pages │ │ ├── about │ │ │ ├── index.tsx │ │ │ └── manifest.ts │ │ ├── index.ts │ │ ├── layout-view │ │ │ ├── README.md │ │ │ ├── index.tsx │ │ │ └── layout-view-screen.tsx │ │ └── tool-box │ │ │ └── index.tsx │ └── routing │ │ ├── README.md │ │ ├── index.ts │ │ ├── layout-preference.ts │ │ ├── navigation-store │ │ ├── README.md │ │ ├── index.ts │ │ └── save-workmode-work.ts │ │ ├── pages.ts │ │ ├── primary-workmode-selector.ts │ │ ├── release-visibility-preference.ts │ │ ├── router.ts │ │ ├── work-mode.ts │ │ └── work-screen.ts └── package.json ├── branding ├── assistant-cover-v0.1.1.png ├── assistant-cover-v2021.2.0.png ├── assistant-cover-v2021.8.0.png ├── assistant-logo-v0.1.1.png └── design-assistant-icons-loader.png ├── docs ├── gifs │ ├── assistant-demo-2021.0.1.gif │ ├── assistant-icons-loader-2021.0.1f.gif │ └── quicklook-demo-v002.gif └── images │ ├── assistant-webdev-example.png │ ├── plugin-flutter-example-v0.0.1.png │ ├── plugin-flutter-example-v0.0.2.png │ └── plugin-flutter-example.png ├── example └── README.md ├── figma-core ├── code-thread │ ├── broadcast-selection-preview.ts │ ├── core-init.ts │ ├── default-handler.ts │ ├── index.ts │ ├── message-handler.ts │ ├── resize-screen.ts │ ├── runon.ts │ ├── selection.ts │ ├── show-ui.ts │ └── user-interest.ts ├── contents-extraction │ └── README.md ├── event-handlers │ ├── README.md │ ├── apply-image.ts │ ├── apply-text-characters.ts │ ├── create-button.ts │ ├── create-icon.ts │ ├── hide-all.ts │ ├── index.ts │ ├── init.ts │ ├── randomize-selection.ts │ └── replace-font.ts ├── index.ts ├── node-cache │ ├── README.md │ ├── index.ts │ └── memoize │ │ ├── README.md │ │ ├── config.ts │ │ └── index.ts ├── package.json ├── physical-visual-store │ ├── README.md │ ├── checksum │ │ └── is-managed-node.ts │ ├── index.ts │ ├── page-manager │ │ ├── craete-page-if-non-exist.ts │ │ ├── create-readme.ts │ │ └── index.ts │ └── used-emoji │ │ ├── README.md │ │ └── index.ts ├── platform-features │ ├── README.md │ ├── file-checksum │ │ ├── README.md │ │ ├── api.ts │ │ ├── index.ts │ │ └── store.ts │ └── index.ts ├── reflect-render │ ├── README.md │ ├── buttons.render │ │ └── index.ts │ ├── cgrect.render │ │ └── index.ts │ ├── icons.render │ │ ├── README.md │ │ └── index.ts │ ├── image.render │ │ └── index.ts │ ├── index.ts │ ├── text.render │ │ └── index.ts │ └── textstyle.render │ │ └── index.ts ├── relaunch-data │ ├── README.md │ ├── index.ts │ └── relaunch-data-example.png └── tool-box │ ├── manipulate │ ├── README.md │ ├── font-replacer │ │ ├── README.md │ │ └── index.ts │ ├── hide-all │ │ ├── README.md │ │ └── index.ts │ ├── index.ts │ └── text-randomize │ │ └── index.ts │ └── slot │ └── README.md ├── figma-native ├── .env.defaults ├── .gitignore ├── README.md ├── manifest.json ├── package.json ├── src │ ├── code.ts │ ├── ui.html │ └── ui.tsx ├── tsconfig.json └── webpack.config.js ├── figma ├── .gitignore ├── ABOUT.md ├── CONTRIBUTING.md ├── README.md ├── manifest.json ├── package.json ├── scripts │ └── optimize.js ├── src │ ├── code.ts │ ├── handle-proxy-requests.ts │ ├── ui.html │ └── ui.tsx ├── tsconfig.json ├── tsconfig.prod.json └── webpack.config.js ├── go.mod ├── package.json ├── packages ├── README.md ├── _firstparty-analytics │ ├── README.md │ ├── index.ts │ └── package.json ├── _firstparty-auth │ ├── README.md │ ├── index.ts │ ├── no-auth-trial-manager.ts │ ├── package.json │ └── storage.ts ├── _firstparty-early-access │ ├── guards │ │ └── index.ts │ ├── hooks │ │ ├── index.ts │ │ └── use-early-access.tsx │ ├── index.ts │ ├── k.ts │ ├── package.json │ ├── register.tsx │ ├── scaffolds │ │ ├── join-the-waitlist-card.tsx │ │ └── register-with-code-card.tsx │ └── store.ts ├── _logger │ ├── index.ts │ └── package.json ├── _utils │ ├── debounce.ts │ └── package.json ├── app-auth │ ├── index.ts │ ├── package.json │ └── signin │ │ ├── signin-prompts.tsx │ │ ├── signin-screen.tsx │ │ └── style.ts ├── app-component-manage │ ├── README.md │ ├── component-codebox.tsx │ ├── component-view-screen.tsx │ ├── index.ts │ ├── package.json │ └── schema-editor.tsx ├── app-copywriter │ ├── client │ │ └── index.ts │ ├── components │ │ ├── bubble.tsx │ │ ├── group-label.tsx │ │ ├── index.ts │ │ └── prompt-input-box.tsx │ ├── copywriter.tsx │ ├── index.ts │ └── package.json ├── app-data-mapper │ ├── README.md │ ├── __plugin │ │ ├── events.ts │ │ └── index.ts │ ├── data-mapper-screen.tsx │ ├── data-source-node.tsx │ ├── example-data-source.ts │ ├── index.ts │ ├── mock-data-example.json │ └── package.json ├── app-design-lint │ ├── README.md │ ├── __plugin │ │ ├── events.ts │ │ └── index.ts │ ├── actions │ │ └── index.ts │ ├── error-by-layer-item.tsx │ ├── fix-your-self.tsx │ ├── group-by │ │ ├── README.md │ │ └── index.ts │ ├── hooks │ │ └── README.md │ ├── index.ts │ ├── lint-colors.ts │ ├── lint-error-icon.tsx │ ├── lint-item-row │ │ ├── index.ts │ │ └── lint-item-row.tsx │ ├── lint-level-indicator.tsx │ ├── lint-list-view │ │ └── index.tsx │ ├── lint-option-choice-item.tsx │ ├── lint-process-paginator.tsx │ ├── lint-screen.tsx │ ├── lint-tree-view │ │ ├── index.ts │ │ └── lint-tree-view.tsx │ └── package.json ├── app-design-preview │ ├── api.ts │ ├── components │ │ ├── fullscreen-appbar-action-button.tsx │ │ ├── fullscreen-appbar.tsx │ │ ├── index.ts │ │ └── publish.tsx │ ├── index.ts │ ├── package.json │ └── preview-screen.tsx ├── app-design-text-code-syntax-hightlight │ ├── LICENSE │ ├── README.md │ ├── __plugin │ │ ├── change-color-usecase.ts │ │ ├── event.ts │ │ └── index.ts │ ├── color-schema │ │ ├── color-schemaList.ts │ │ ├── index.ts │ │ └── schemas │ │ │ ├── a11yDark.ts │ │ │ ├── a11yLight.ts │ │ │ ├── agate.ts │ │ │ ├── anOldHope.ts │ │ │ ├── androidstudio.ts │ │ │ ├── arduinoLight.ts │ │ │ ├── arta.ts │ │ │ ├── ascetic.ts │ │ │ ├── atelierCaveDark.ts │ │ │ ├── atelierCaveLight.ts │ │ │ ├── atelierDuneDark.ts │ │ │ ├── atelierDuneLight.ts │ │ │ ├── atelierEstuaryDark.ts │ │ │ ├── atelierEstuaryLight.ts │ │ │ ├── atelierForestDark.ts │ │ │ ├── atelierForestLight.ts │ │ │ ├── atelierHeathDark.ts │ │ │ ├── atelierHeathLight.ts │ │ │ ├── atelierLakesideDark.ts │ │ │ ├── atelierLakesideLight.ts │ │ │ ├── atelierPlateauDark.ts │ │ │ ├── atelierPlateauLight.ts │ │ │ ├── atelierSavannaDark.ts │ │ │ ├── atelierSavannaLight.ts │ │ │ ├── atelierSeasideDark.ts │ │ │ ├── atelierSeasideLight.ts │ │ │ ├── atelierSulphurpoolDark.ts │ │ │ ├── atelierSulphurpoolLight.ts │ │ │ ├── atomOneDark.ts │ │ │ ├── atomOneDarkReasonable.ts │ │ │ ├── atomOneLight.ts │ │ │ ├── brownPaper.ts │ │ │ ├── codepenEmbed.ts │ │ │ ├── colorBrewer.ts │ │ │ ├── darcula.ts │ │ │ ├── dark.ts │ │ │ ├── defaultColor.ts │ │ │ ├── docco.ts │ │ │ ├── dracula.ts │ │ │ ├── far.ts │ │ │ ├── foundation.ts │ │ │ ├── github.ts │ │ │ ├── githubGist.ts │ │ │ ├── gml.ts │ │ │ ├── googlecode.ts │ │ │ ├── gorilla.ts │ │ │ ├── gorillaColorSchema.ts │ │ │ ├── grayscale.ts │ │ │ ├── gruvboxDark.ts │ │ │ ├── gruvboxLight.ts │ │ │ ├── hopscotch.ts │ │ │ ├── hybrid.ts │ │ │ ├── idea.ts │ │ │ ├── irBlack.ts │ │ │ ├── isblEditorDark.ts │ │ │ ├── isblEditorLight.ts │ │ │ ├── kimbieDark.ts │ │ │ ├── kimbieLight.ts │ │ │ ├── lightfair.ts │ │ │ ├── magula.ts │ │ │ ├── monoBlue.ts │ │ │ ├── monokai.ts │ │ │ ├── monokaiSublime.ts │ │ │ ├── noctis.ts │ │ │ ├── nord.ts │ │ │ ├── obsidian.ts │ │ │ ├── ocean.ts │ │ │ ├── paraisoDark.ts │ │ │ ├── paraisoLight.ts │ │ │ ├── pojoaque.ts │ │ │ ├── purebasic.ts │ │ │ ├── qtcreatorDark.ts │ │ │ ├── qtcreatorLight.ts │ │ │ ├── railscasts.ts │ │ │ ├── rainbow.ts │ │ │ ├── routeros.ts │ │ │ ├── schoolBook.ts │ │ │ ├── shadesOfPurple.ts │ │ │ ├── solarizedDark.ts │ │ │ ├── solarizedLight.ts │ │ │ ├── sunburst.ts │ │ │ ├── tomorrow.ts │ │ │ ├── tomorrowNight.ts │ │ │ ├── tomorrowNightBlue.ts │ │ │ ├── tomorrowNightBright.ts │ │ │ ├── tomorrowNightEighties.ts │ │ │ ├── vs.ts │ │ │ ├── vs2015.ts │ │ │ ├── xcode.ts │ │ │ ├── xt256.ts │ │ │ └── zenburn.ts │ ├── components │ │ ├── highlight-executor.tsx │ │ └── select.tsx │ ├── design-text-code-syntax-highligh-screen.css │ ├── design-text-code-syntax-highligh-screen.tsx │ ├── index.ts │ ├── language │ │ ├── index.ts │ │ └── language-list.ts │ ├── models │ │ ├── index.ts │ │ └── schema-and-language.ts │ ├── package.json │ └── preferences │ │ └── index.ts ├── app-design-to-code │ ├── __plugin │ │ ├── design-to-code.ts │ │ ├── events.ts │ │ └── index.ts │ ├── code-options-control.tsx │ ├── code-screen.tsx │ ├── code-session-cache-storage.ts │ ├── code-view-with-control.tsx │ ├── constants.ts │ ├── footer-action │ │ ├── code-screen-footer.tsx │ │ ├── index.ts │ │ └── legacy-next-upload-button.tsx │ ├── formatter.ts │ ├── framework-option.ts │ ├── index.ts │ ├── package.json │ └── user-options.ts ├── app-i18n │ ├── i18n-screen.tsx │ ├── index.ts │ └── package.json ├── app-icons-loader │ ├── history.ts │ ├── icon-item.tsx │ ├── icons-loader.tsx │ ├── icons-screen.tsx │ ├── icons-search.tsx │ ├── index.ts │ ├── package.json │ ├── resources.ts │ ├── search.ts │ └── utils.ts ├── app-live-session │ ├── CONTRIBUTING.md │ ├── README.md │ ├── components │ │ ├── connection-and-user-selection-interactive-indicator.tsx │ │ └── index.ts │ ├── index.ts │ ├── k │ │ └── index.ts │ ├── layouts │ │ ├── connected.tsx │ │ ├── filekey-setup-required.tsx │ │ ├── index.ts │ │ ├── onboarding.tsx │ │ ├── signin-required.tsx │ │ └── start.tsx │ ├── package.json │ ├── pages │ │ ├── index.ts │ │ └── main.tsx │ ├── session-api │ │ └── index.ts │ └── storage │ │ ├── index.ts │ │ └── need-to-show-onboarding.ts ├── app-meta-editor │ ├── batch-meta-editor │ │ ├── README.md │ │ └── index.tsx │ ├── index.ts │ ├── meta-editor │ │ ├── README.md │ │ └── index.tsx │ ├── mock │ │ └── index.ts │ ├── package.json │ └── repository │ │ └── index.ts ├── app-photo-loader │ ├── client.ts │ ├── image-item.tsx │ ├── image-prompt-box.tsx │ ├── index.ts │ ├── k.ts │ ├── package.json │ ├── photo-loader.tsx │ └── photo-screen.tsx ├── app-preferences │ ├── index.ts │ ├── package.json │ ├── prefer-framework │ │ └── index.ts │ └── prefer-language │ │ └── index.ts ├── app-scene-export-json │ ├── README.md │ ├── export-utils.ts │ ├── exporter.tsx │ ├── figma-exporter.tsx │ ├── index.tsx │ ├── package.json │ └── vanilla-exporter.tsx ├── app-scene-view │ ├── _wrapping-for-hosting.ts │ ├── index.ts │ ├── package.json │ ├── register-scene.ts │ └── scene-preview.ts ├── app-schema-editor │ ├── README.md │ ├── by-selection-state │ │ ├── _shared-components │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── selection-base-master-component.tsx │ │ ├── selection-configurable-layer.coli.ts │ │ ├── selection-configurable-layer.tsx │ │ ├── selection-instance-component.coli.ts │ │ ├── selection-instance-component.tsx │ │ ├── selection-invalid.tsx │ │ ├── selection-master-component.coli.ts │ │ ├── selection-master-component.tsx │ │ ├── selection-none.tsx │ │ ├── selection-variant-instance.tsx │ │ ├── selection-variant-master.tsx │ │ └── selection-variant-set.tsx │ ├── components │ │ ├── property-field-lookup-hover-card.tsx │ │ ├── props-interface-view.tsx │ │ └── single-property.tsx │ ├── index.ts │ ├── interface-code-builder │ │ ├── example-data-builder.ts │ │ ├── index.ts │ │ ├── jsx-view-example-builder.ts │ │ ├── props-builder.ts │ │ ├── scoped-property-id-namer.ts │ │ ├── single-layer-property-mapping-to-property-signature.ts │ │ └── type-to-coli-type.ts │ ├── package.json │ ├── property-suggestions │ │ └── index.ts │ ├── schema-editor.tsx │ ├── storage │ │ └── index.ts │ ├── types │ │ ├── index.ts │ │ └── single-layer-property-type.ts │ └── ux-messages │ │ └── index.ts ├── app-toolbox-home │ ├── index.ts │ ├── package.json │ └── toolbox-home.tsx ├── app-widget-maker-button │ ├── button-maker-screen.tsx │ ├── index.ts │ └── package.json ├── core-code-formatter │ ├── dart-format.ts │ └── package.json ├── core-constant │ ├── ek.constant.ts │ ├── index.ts │ ├── ns.constant.ts │ └── package.json ├── icons-util │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ └── package.json ├── platform-figma-checksum │ ├── __plugin │ │ ├── events.ts │ │ └── index.ts │ ├── components │ │ ├── index.ts │ │ └── link-input.tsx │ ├── index.ts │ ├── package.json │ ├── pages │ │ └── index.tsx │ └── store.ts ├── plugin-app │ ├── README.md │ ├── client-id │ │ ├── README.md │ │ ├── index.ts │ │ └── store.ts │ ├── index.ts │ ├── package.json │ ├── plugin-app.tsx │ ├── plugin-hooks │ │ ├── README.md │ │ ├── index.ts │ │ ├── use-meta.ts │ │ └── use-selection.ts │ ├── states │ │ └── canvas.ts │ └── utils │ │ ├── canvas.ts │ │ └── index.ts ├── plugin-sdk-app │ ├── _shared-storage-cache.ts │ ├── index.ts │ ├── node-api.ts │ ├── package.json │ └── plugin-sdk.ts ├── plugin-sdk-core │ ├── _id │ │ └── index.ts │ ├── events.ts │ ├── index.ts │ ├── interfaces │ │ ├── dragdrop │ │ │ ├── dragdrop.requests.ts │ │ │ ├── dragdrop.responses.ts │ │ │ ├── dragdrop.types.ts │ │ │ └── index.ts │ │ ├── export-image │ │ │ ├── export-image.requests.ts │ │ │ ├── export-image.responses.ts │ │ │ ├── export-image.types.ts │ │ │ └── index.ts │ │ ├── focus │ │ │ ├── focus.requests.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── meta │ │ │ ├── index.ts │ │ │ ├── meta.requests.ts │ │ │ ├── meta.responses.ts │ │ │ └── meta.types.ts │ │ ├── notify │ │ │ ├── index.ts │ │ │ └── notify.requests.ts │ │ ├── remote-api │ │ │ ├── index.ts │ │ │ ├── remote-api.requests.ts │ │ │ └── remote-api.responses.ts │ │ ├── storage │ │ │ ├── index.ts │ │ │ ├── storage.request.ts │ │ │ └── storage.response.ts │ │ └── uicontrol │ │ │ ├── index.ts │ │ │ └── uicontrol.request.ts │ ├── package.json │ └── target-platform │ │ └── index.ts ├── plugin-sdk-draggable │ ├── README.md │ ├── index.tsx │ └── package.json ├── plugin-sdk-service │ ├── README.md │ ├── index.ts │ ├── package.json │ └── storage │ │ ├── README.md │ │ ├── figma.storage.ts │ │ ├── index.ts │ │ ├── istorage.ts │ │ ├── metadata │ │ ├── README.md │ │ └── index.ts │ │ ├── payload-handle.ts │ │ ├── universal.storage.ts │ │ └── web.storage.ts ├── toolbox-font-replacer │ ├── font-replacer-screen.tsx │ ├── index.ts │ └── package.json ├── toolbox-realtime-selection-sync │ └── README.md ├── ui-code-box │ ├── README.md │ ├── codebox-edit-dialog.tsx │ ├── codebox.tsx │ ├── editors │ │ ├── index.ts │ │ ├── monaco-editor.tsx │ │ ├── monaco-utils │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ └── register.ts │ │ └── prism-view.tsx │ ├── index.ts │ └── package.json ├── ui-core │ ├── button-style │ │ └── index.ts │ ├── button │ │ └── index.ts │ ├── column │ │ └── index.ts │ ├── divider │ │ ├── divider.tsx │ │ └── index.ts │ ├── index.ts │ ├── package.json │ ├── row │ │ └── index.ts │ └── search │ │ ├── index.ts │ │ └── search.tsx ├── ui-flow-steps │ ├── components │ │ ├── animated-check-icon.tsx │ │ ├── animated-progress-bar.tsx │ │ └── index.ts │ ├── index.ts │ ├── package.json │ └── scaffold │ │ ├── index.ts │ │ └── upload-steps.tsx ├── ui-icons │ ├── arrow-left.tsx │ ├── back-arrow.tsx │ ├── caret-down.tsx │ ├── caret-left.tsx │ ├── caret-right.tsx │ ├── caret-up.tsx │ ├── check.tsx │ ├── empty-indicator-icon.tsx │ ├── expand-down.tsx │ ├── expand-right.tsx │ ├── index.ts │ ├── package.json │ ├── pagination-left.tsx │ ├── pagination-right.tsx │ └── warning.tsx ├── ui-lint-icons │ ├── error-missing-color-style.tsx │ ├── error-missing-text-style.tsx │ ├── error-naming.tsx │ ├── index.ts │ └── package.json ├── ui-previewer │ ├── .design │ │ └── design-concept-archive.png │ ├── README.md │ ├── cache │ │ └── index.ts │ ├── components │ │ ├── esbuild-result-preview.tsx │ │ ├── index.ts │ │ ├── interactive-canvas.tsx │ │ └── preview-empty.tsx │ ├── index.ts │ ├── package.json │ ├── preview-static-snapshot │ │ ├── README.md │ │ └── index.tsx │ ├── preview │ │ └── index.tsx │ └── utils │ │ ├── index.ts │ │ └── inject-asset-source.ts ├── ui-skeleton │ ├── index.ts │ ├── package.json │ └── skeleton.tsx └── ui-theme │ ├── dark.ts │ ├── index.ts │ ├── light.ts │ ├── media-query.ts │ ├── package.json │ └── theme-provider.tsx ├── services ├── .gitignore ├── README.md ├── assistant-early-access │ ├── READMD.md │ └── scripts │ │ ├── dev-activation-key-gen.ts │ │ ├── dev-totp-key-gen.ts │ │ ├── dev-totp-qrcode.ts │ │ ├── out │ │ └── .gitignore │ │ ├── package.json │ │ └── yarn.lock └── live-session-auhorize │ ├── .env.local │ ├── app.ts │ ├── handler.ts │ ├── jest.config.js │ ├── package.json │ ├── serverless.yml │ ├── tsconfig.json │ ├── webpack.config.js │ └── yarn.lock ├── sketch ├── .gitignore ├── README.md ├── assets │ └── icon.png ├── package.json ├── resources │ ├── style.css │ ├── webview.html │ └── webview.js ├── sketch-assets │ └── icons.sketch ├── src │ ├── manifest.json │ └── my-command.js └── webpack.skpm.config.js ├── tests └── README.md ├── tsconfig.json ├── web ├── .env ├── .gitignore ├── README.md ├── lib │ └── gtag.js ├── next-env.d.ts ├── next.config.js ├── package.json ├── pages │ ├── _app.tsx │ ├── _document.tsx │ ├── api │ │ ├── generative │ │ │ ├── images.ts │ │ │ └── texts.ts │ │ ├── live-session │ │ │ └── auth.ts │ │ ├── resources │ │ │ └── images.ts │ │ └── translation │ │ │ └── detect.ts │ ├── index.tsx │ ├── init-figma.tsx │ └── init-webdev.tsx ├── public │ ├── _ │ │ └── early-access │ │ │ └── background.png │ ├── assets │ │ └── images │ │ │ ├── artwork-app-grouped-figma-grida-vscode.png │ │ │ ├── artwork-figma-desktop-where-is-share-button.png │ │ │ ├── empty-state-icon.png │ │ │ ├── mac-icon-grida.png │ │ │ └── mac-icon-vscode.png │ └── favicon.ico ├── service │ ├── providers │ │ └── openai.ts │ └── translation │ │ ├── detect.ts │ │ ├── index.ts │ │ ├── translate-for-text-to-image.ts │ │ └── translate.ts ├── tsconfig.json └── utils │ └── platform-init-query.ts ├── xd ├── .gitignore ├── README.md ├── debug.json ├── images │ ├── icon@1x.png │ ├── icon@2x.png │ ├── icon@3x.png │ ├── icon@4x.png │ └── icon@5x.png ├── manifest.json ├── package.json ├── scripts │ └── deploy.js ├── src │ ├── lib │ │ └── index.js │ └── ui │ │ └── main.tsx ├── tsconfig.json └── webpack.config.js ├── yarn.lock └── zeplin ├── .gitignore ├── .npmignore ├── README.md ├── package.json └── src ├── fixtures ├── components.json ├── index.js ├── project.json ├── screens.json └── version.json ├── index.js └── index.test.js /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[Bug]" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - Platform: [Figma / Sketch / XD] 29 | - OS: [Mac / Windows] 30 | - Browser [e.g. chrome, safari] 31 | - Version [e.g. 202x.0.x.x] 32 | 33 | **Additional context** 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: General tests 2 | on: [pull_request] 3 | jobs: 4 | compile-build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - uses: actions/setup-node@v2 9 | with: 10 | node-version: "14" 11 | - run: git submodule update --init --recursive 12 | - run: yarn 13 | - run: yarn test 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | .idea 5 | package.lock 6 | webdev/.eslintcache 7 | 8 | 9 | # we use yarn 10 | package-lock.json 11 | 12 | # log including yarn error log 13 | .log -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages/lint"] 2 | path = packages/lint 3 | url = https://github.com/reflect-ui/design-lint 4 | [submodule "packages/base-sdk"] 5 | path = packages/base-sdk 6 | url = https://github.com/gridaco/base-sdk 7 | [submodule "packages/reflect-ui-generator"] 8 | path = packages/reflect-ui-generator 9 | url = https://github.com/reflect-ui/reflect-ui-generator 10 | [submodule "packages/design-to-code"] 11 | path = packages/design-to-code 12 | url = https://github.com/gridaco/designto-code 13 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: [ 3 | "../app/lib/components/**/*.stories.mdx", 4 | "../app/lib/components/**/*.stories.@(js|jsx|ts|tsx)", 5 | ], 6 | addons: ["@storybook/addon-links", "@storybook/addon-essentials"], 7 | }; 8 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | export const parameters = { 2 | actions: { argTypesRegex: "^on[A-Z].*" }, 3 | controls: { 4 | matchers: { 5 | color: /(background|color)$/i, 6 | date: /Date$/, 7 | }, 8 | }, 9 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true, 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/.svn": true, 6 | "**/.hg": true, 7 | "**/CVS": true, 8 | "**/.DS_Store": true, 9 | "**/dist": true, 10 | "**/node_modules": true 11 | }, 12 | "search.exclude": { 13 | "**/node_modules": true, 14 | "**/bower_components": true, 15 | "**/*.code-search": true, 16 | "**/yarn.lock": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Grida Standard License 2 | 3 | Copyright (c) 2020 Grida.co (Previously Bridged) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense the Software. 9 | selling / re-distributing copies of this software is not allowed. 10 | And to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | ## Testing infra & docs -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 | # Assistant shared app (ui) library 2 | -------------------------------------------------------------------------------- /app/__plugin__init__/README.md: -------------------------------------------------------------------------------- 1 | # Plugin init folder to configure fles to be included 2 | -------------------------------------------------------------------------------- /app/__plugin__init__/index.ts: -------------------------------------------------------------------------------- 1 | // DO NOT REMOVE THIS LINE 2 | import "@app/design-to-code/__plugin"; 3 | import "@app/design-lint/__plugin"; 4 | 5 | // disabled on staging 6 | // import "@app/data-mapper/__plugin"; 7 | // import "@app/design-text-code-syntax-highlight/__plugin"; 8 | -------------------------------------------------------------------------------- /app/lib/app.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif; 3 | } 4 | 5 | body { 6 | /* for reset user agnet style -> margin: 8px */ 7 | margin: 0px; 8 | } 9 | 10 | /* 11 | If you want to change the font, be sure to check the following! 12 | tippy-1 is `tippyjs' id. it is only for drop item in @code-ui/docstring 13 | */ 14 | #tippy-1 li { 15 | font-family: "Source Code Pro", "Courier New", "Lucida Console", Monaco; 16 | } 17 | 18 | #create { 19 | box-shadow: none; 20 | background: #18a0fb; 21 | color: white; 22 | } 23 | 24 | #create:focus { 25 | box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.3); 26 | } 27 | 28 | .jss3 { 29 | background-color: #000 !important; 30 | } 31 | 32 | /* for selected tab under line color */ 33 | 34 | .PrivateTabIndicator-colorSecondary-3 { 35 | background-color: #000 !important; 36 | } 37 | 38 | /* for tabs font color switch select */ 39 | 40 | .MuiTab-textColorInherit.Mui-selected { 41 | opacity: 1 !important; 42 | font-weight: bold !important; 43 | } 44 | 45 | .MuiTab-textColorInherit { 46 | opacity: 0.4 !important; 47 | font-weight: initial !important; 48 | } 49 | -------------------------------------------------------------------------------- /app/lib/app.css.d.ts: -------------------------------------------------------------------------------- 1 | declare const styles: { 2 | readonly "create": string; 3 | }; 4 | export = styles; 5 | 6 | -------------------------------------------------------------------------------- /app/lib/components/animated/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./reveal-when-visible"; 2 | -------------------------------------------------------------------------------- /app/lib/components/animated/reveal-when-visible.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useInView } from "react-intersection-observer"; 3 | import { motion } from "framer-motion"; 4 | 5 | /** 6 | * A general component that can be used to animate a component when it is visible. 7 | * @returns 8 | */ 9 | export function RevealWhenVisible({ 10 | children, 11 | initialY = 0, 12 | initialOpacity = 0, 13 | duration = 0.5, 14 | }: { 15 | children: React.ReactNode; 16 | initialY?: number; 17 | initialOpacity?: number; 18 | duration?: number; 19 | }) { 20 | const [ref, inView] = useInView({ 21 | triggerOnce: true, 22 | rootMargin: "-100px 0px", 23 | }); 24 | 25 | const variants = { 26 | visible: { 27 | y: 0, 28 | opacity: 1, 29 | }, 30 | hidden: { 31 | y: initialY, 32 | opacity: initialOpacity, 33 | }, 34 | }; 35 | 36 | return ( 37 | 46 | {children} 47 | 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /app/lib/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./open-in-editor-button"; 2 | -------------------------------------------------------------------------------- /app/lib/components/motions/README.md: -------------------------------------------------------------------------------- 1 | # General motions 2 | 3 | Motions only ! - no symantic ui components allowed here. 4 | -------------------------------------------------------------------------------- /app/lib/components/motions/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./update-hide-by-scroll-position-and-velocity"; 2 | export * from "./smooth-dampings"; 3 | -------------------------------------------------------------------------------- /app/lib/components/motions/smooth-dampings/index.ts: -------------------------------------------------------------------------------- 1 | export const smooth_damping_hide_motion_transition = { 2 | ease: [0.1, 0.25, 0.3, 1], 3 | duration: 0.6, 4 | }; 5 | -------------------------------------------------------------------------------- /app/lib/components/navigation/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./primary-workmode-select"; 2 | export * from "./secondary-menu-dropdown"; 3 | export * from "./secondary-workmode-choice"; 4 | export * from "./secondary-workmode-menu"; 5 | export * from "./navigator-expansion-control-button"; 6 | export * from "./workmode-screen-tabs"; 7 | -------------------------------------------------------------------------------- /app/lib/components/navigation/navigator-expansion-control-button.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks"; 2 | import { NavigatorExpansionControlButton } from "./navigator-expansion-control-button"; 3 | 4 | 5 | 6 | Close or expand button used for global navigation. 7 | 8 | # Preview 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | # Props 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/lib/components/navigation/navigator-expansion-control-button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ExpandLessIcon from "@material-ui/icons/ExpandLess"; 3 | import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; 4 | import styled from "@emotion/styled"; 5 | 6 | export function NavigatorExpansionControlButton(props: { 7 | action: "expand" | "close"; 8 | onClick: () => void; 9 | }) { 10 | const icon = () => { 11 | switch (props.action) { 12 | case "expand": 13 | return ( 14 | <> 15 | 16 | 17 | ); 18 | case "close": 19 | return ( 20 | <> 21 | 22 | 23 | ); 24 | } 25 | }; 26 | 27 | return ; 28 | } 29 | 30 | const Button = styled.div` 31 | cursor: pointer; 32 | align-items: center; 33 | display: flex; 34 | margin-left: auto; 35 | 36 | svg { 37 | fill: #cfcfcf; 38 | } 39 | `; 40 | -------------------------------------------------------------------------------- /app/lib/components/navigation/primary-workmode-select.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks"; 2 | import { PrimaryWorkmodeSelect } from "./primary-workmode-select"; 3 | 4 | 5 | 6 | Primary workmode selector for navigation. 7 | 8 | # Preview 9 | 10 | 11 | 12 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | # Props 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/lib/components/navigation/primary-workmode-select.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { PrimaryWorkmodeSet, WorkMode } from "../../routing"; 3 | import { WorkmodeButton } from "./work-mode-button"; 4 | 5 | export function PrimaryWorkmodeSelect(props: { 6 | set: PrimaryWorkmodeSet; 7 | selection: WorkMode; 8 | onSelect: (selection: WorkMode) => void; 9 | }) { 10 | const _is_active = (mode: WorkMode) => { 11 | return mode == props.selection; 12 | }; 13 | 14 | return ( 15 | <> 16 | { 20 | props.onSelect(props.set.first); 21 | }} 22 | /> 23 | { 27 | props.onSelect(props.set.second); 28 | }} 29 | /> 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/lib/components/navigation/route-back-button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | import { useHistory } from "react-router"; 4 | import BackArrow from "@assistant/icons/back-arrow"; 5 | 6 | export function RouteBackButton({ onClick }: { onClick?: () => void }) { 7 | const history = useHistory(); 8 | 9 | const close = () => { 10 | onClick ? onClick() : history.goBack(); 11 | }; 12 | 13 | return ( 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export const BackIcon = styled.div` 21 | width: 24px; 22 | height: 24px; 23 | cursor: pointer; 24 | `; 25 | -------------------------------------------------------------------------------- /app/lib/components/navigation/secondary-workmode-choice.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React from "react"; 3 | 4 | export function SecondaryWorkmodeChoice(props: { 5 | name: string; 6 | disabled?: boolean; 7 | onClick: () => void; 8 | }) { 9 | return {props.name}; 10 | } 11 | 12 | const Title = styled.h6` 13 | font-size: 19px; 14 | font-weight: 700; 15 | line-height: 26px; 16 | letter-spacing: 0em; 17 | text-align: left; 18 | color: #cfcfcf; 19 | cursor: pointer; 20 | text-transform: capitalize; 21 | margin: 0; // for reset h6 inital margin 22 | margin-right: 10px; 23 | user-select: none; 24 | 25 | /* &:nth-child(3n) { 26 | margin-right: 0; 27 | } */ 28 | 29 | &:hover { 30 | color: #606060; 31 | } 32 | `; 33 | -------------------------------------------------------------------------------- /app/lib/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./main"; 2 | -------------------------------------------------------------------------------- /app/lib/main/global-state-atoms.ts: -------------------------------------------------------------------------------- 1 | import { atom } from "recoil"; 2 | 3 | export interface EditorSizeProps { 4 | width: number; 5 | height: number; 6 | } 7 | 8 | export const hide_navigation = atom({ 9 | key: "hide_navigation", 10 | default: false, 11 | }); 12 | -------------------------------------------------------------------------------- /app/lib/pages/about/manifest.ts: -------------------------------------------------------------------------------- 1 | // const _package = require("../package.jsonn"); 2 | export const name = "Grida Assistant"; 3 | export const version = "2023.3.1f0"; /*_package.version*/ 4 | export const versionText = `v${version}`; 5 | -------------------------------------------------------------------------------- /app/lib/pages/index.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// re-exports all the pages 3 | /// 4 | 5 | export { GlobalizationScreen } from "@app/i18n"; 6 | -------------------------------------------------------------------------------- /app/lib/pages/layout-view/README.md: -------------------------------------------------------------------------------- 1 | # Layout inspector 2 | -------------------------------------------------------------------------------- /app/lib/pages/layout-view/index.tsx: -------------------------------------------------------------------------------- 1 | export { LayoutViewScreen } from "./layout-view-screen"; 2 | -------------------------------------------------------------------------------- /app/lib/pages/layout-view/layout-view-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export function LayoutViewScreen() { 4 | // PluginSdk.selectedNodeId; 5 | return

Layout view

; 6 | } 7 | -------------------------------------------------------------------------------- /app/lib/routing/README.md: -------------------------------------------------------------------------------- 1 | # Navigation management UI & Logics container -------------------------------------------------------------------------------- /app/lib/routing/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./navigation-store"; 2 | export * from "./layout-preference"; 3 | export * from "./work-mode"; 4 | export * from "./work-screen"; 5 | export * from "./primary-workmode-selector"; 6 | export * from "./pages"; 7 | export * from "./router"; 8 | -------------------------------------------------------------------------------- /app/lib/routing/navigation-store/README.md: -------------------------------------------------------------------------------- 1 | # Navigation store saving layout (workmode set + last workmode + last tab) 2 | 3 | ## Supported platforms 4 | 5 | - webdev 6 | - sketch 7 | 8 | ## Layout 9 | 10 | - get/set last work by workmode 11 | -------------------------------------------------------------------------------- /app/lib/routing/navigation-store/save-workmode-work.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | import { WorkMode } from "../work-mode"; 3 | import { WorkScreen } from "../work-screen"; 4 | 5 | async function _set_work_by_workmode(workmode: WorkMode, work: string) { 6 | PluginSdk.setItem(_make_id(workmode), work); 7 | } 8 | 9 | async function _get_work_by_workmode(workmode: WorkMode) { 10 | const saved = await PluginSdk.getItem(_make_id(workmode)); 11 | if (!saved) { 12 | return _default_work_by_workmode(workmode); 13 | } 14 | } 15 | 16 | function _default_work_by_workmode(workmode: WorkMode): WorkScreen { 17 | switch (workmode) { 18 | case WorkMode.code: 19 | return WorkScreen.code; 20 | case WorkMode.design: 21 | return WorkScreen.icon; 22 | } 23 | } 24 | 25 | function _make_id(workmode: WorkMode): string { 26 | return `workmode-current-work-of-${workmode}`; 27 | } 28 | 29 | /// 30 | /// region export 31 | /// 32 | export const saved_work_by_workmode = { 33 | set: _set_work_by_workmode, 34 | get: _get_work_by_workmode, 35 | }; 36 | /// 37 | /// endregion export 38 | /// 39 | -------------------------------------------------------------------------------- /app/lib/routing/primary-workmode-selector.ts: -------------------------------------------------------------------------------- 1 | import { WorkMode } from "./work-mode"; 2 | export interface PrimaryWorkmodeSet { 3 | first: WorkMode; 4 | second: WorkMode; 5 | } 6 | 7 | export function getPrimaryWorkmodeSet(): PrimaryWorkmodeSet { 8 | return { 9 | first: WorkMode.design, 10 | second: WorkMode.code, 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /app/lib/routing/router.ts: -------------------------------------------------------------------------------- 1 | import { MemoryRouter, BrowserRouter } from "react-router-dom"; 2 | 3 | export const getDedicatedRouter = () => 4 | _is_in_iframe() ? MemoryRouter : BrowserRouter; 5 | 6 | function _is_in_iframe() { 7 | if (process["browser"]) { 8 | // The page is in an iframe 9 | return window.location !== window.parent.location; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/lib/routing/work-mode.ts: -------------------------------------------------------------------------------- 1 | export enum WorkMode { 2 | code = "code", 3 | design = "design", 4 | asset = "asset", 5 | manage = "manage", 6 | tools = "tools", 7 | library = "library", 8 | settings = "settings", // "about" page for now 9 | about = "about", 10 | content = "content", 11 | toolbox = "toolbox", 12 | } 13 | -------------------------------------------------------------------------------- /app/lib/routing/work-screen.ts: -------------------------------------------------------------------------------- 1 | export enum WorkScreen { 2 | about = "about", 3 | /** todo: rename to code/preview */ 4 | code = "code", 5 | /** @deprecated only used for sendig event */ 6 | code_flutter = "code/flutter", 7 | /** @deprecated only used for sendig event */ 8 | code_react = "code/react", 9 | component = "component", 10 | preview = "preview", 11 | layout = "layout", 12 | copy = "copy", 13 | icon = "icon", 14 | photo = "photo", 15 | live = "live", 16 | lint = "lint", 17 | g11n = "g11n", 18 | dev = "dev", 19 | slot = "slot", 20 | exporter = "exporter", 21 | tool_home = "tools", 22 | tool_desing_button_maker = "tool_desing_button_maker", 23 | tool_code_syntax_highlighter = "tool_code_syntax_highlighter", 24 | tool_font_replacer = "tool_font_replacer", 25 | tool_meta_editor = "tool_meta_editor", 26 | tool_batch_meta_editor = "tool_batch_meta_editor", 27 | tool_data_mapper = "tool_data_mapper", 28 | signin = "signin", 29 | upgrade = "upgrade", 30 | } 31 | -------------------------------------------------------------------------------- /branding/assistant-cover-v0.1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/branding/assistant-cover-v0.1.1.png -------------------------------------------------------------------------------- /branding/assistant-cover-v2021.2.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/branding/assistant-cover-v2021.2.0.png -------------------------------------------------------------------------------- /branding/assistant-cover-v2021.8.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/branding/assistant-cover-v2021.8.0.png -------------------------------------------------------------------------------- /branding/assistant-logo-v0.1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/branding/assistant-logo-v0.1.1.png -------------------------------------------------------------------------------- /branding/design-assistant-icons-loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/branding/design-assistant-icons-loader.png -------------------------------------------------------------------------------- /docs/gifs/assistant-demo-2021.0.1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/gifs/assistant-demo-2021.0.1.gif -------------------------------------------------------------------------------- /docs/gifs/assistant-icons-loader-2021.0.1f.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/gifs/assistant-icons-loader-2021.0.1f.gif -------------------------------------------------------------------------------- /docs/gifs/quicklook-demo-v002.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/gifs/quicklook-demo-v002.gif -------------------------------------------------------------------------------- /docs/images/assistant-webdev-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/images/assistant-webdev-example.png -------------------------------------------------------------------------------- /docs/images/plugin-flutter-example-v0.0.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/images/plugin-flutter-example-v0.0.1.png -------------------------------------------------------------------------------- /docs/images/plugin-flutter-example-v0.0.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/images/plugin-flutter-example-v0.0.2.png -------------------------------------------------------------------------------- /docs/images/plugin-flutter-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/docs/images/plugin-flutter-example.png -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example designs and apps built with Bridged 2 | 3 | Please visit https://github.com/bridgedxyz/examples or https://bridged.xyz/docs 4 | -------------------------------------------------------------------------------- /figma-core/code-thread/broadcast-selection-preview.ts: -------------------------------------------------------------------------------- 1 | import { EK_CURRENT_SELECTION_PREVIEW_SOURCE_CHANGED } from "@core/constant/ek.constant"; 2 | import { preset, QuickImageExportPreset } from "@plugin-sdk/core"; 3 | 4 | /** 5 | * extracts the png image of selection, broadcasts to listeners. 6 | * @todo - only broadcast when required. 7 | * @param selection 8 | */ 9 | export function broadcastSelectionPreview(selection: SceneNode) { 10 | exportImage(selection).then((d) => { 11 | figma.ui.postMessage({ 12 | type: EK_CURRENT_SELECTION_PREVIEW_SOURCE_CHANGED, 13 | data: { 14 | source: d, 15 | name: selection.name, 16 | }, 17 | }); 18 | }); 19 | } 20 | 21 | export async function exportImage( 22 | target: SceneNode, 23 | options?: { 24 | preset?: QuickImageExportPreset; 25 | } 26 | ): Promise { 27 | const config = preset(options?.preset ?? "small"); 28 | try { 29 | return await (target as ExportMixin).exportAsync(config); 30 | } catch (_) { 31 | console.warn( 32 | "update required. seems figma started to support `WidgetNode`" 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /figma-core/code-thread/core-init.ts: -------------------------------------------------------------------------------- 1 | // import this file 2 | 3 | import { __register__ as __reguster_default_handler__ } from "./default-handler"; 4 | import { __register__ as __register_resize_screen__ } from "./resize-screen"; 5 | import { __register__ as __register_user_interest__ } from "./user-interest"; 6 | // 7 | __reguster_default_handler__(); 8 | __register_resize_screen__(); 9 | __register_user_interest__(); 10 | // 11 | -------------------------------------------------------------------------------- /figma-core/code-thread/default-handler.ts: -------------------------------------------------------------------------------- 1 | import { addMessageHandler } from "./message-handler"; 2 | import { PluginSdkService } from "@plugin-sdk/service"; 3 | 4 | const defaultMessageHandler = async ( 5 | msg: { type: string; data: any } | any 6 | ) => { 7 | { 8 | const generalHandlingResult = PluginSdkService.handle(msg); 9 | // if event is handled by general event handler, no additional handling is required. 10 | if (generalHandlingResult) { 11 | return; 12 | } 13 | } 14 | }; 15 | 16 | export function __register__() { 17 | addMessageHandler(defaultMessageHandler); 18 | } 19 | -------------------------------------------------------------------------------- /figma-core/code-thread/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./message-handler"; 2 | export * from "./selection"; 3 | -------------------------------------------------------------------------------- /figma-core/code-thread/resize-screen.ts: -------------------------------------------------------------------------------- 1 | import { addEventHandler } from "./message-handler"; 2 | 3 | /// Note. 4 | /// Figma's min size is 100x100. size smaller than 100x100 will be ignored by figma, the full size will be (w100)x(h41+100) where as 41 is a default handle's size 5 | export function __register__() { 6 | addEventHandler("resize", (msg) => { 7 | const MIN_WIDTH = 320; 8 | const MIN_HEIGHT = 568; 9 | const w = Math.max(MIN_WIDTH, msg.size.w); 10 | const h = Math.max(MIN_HEIGHT, msg.size.h); 11 | figma.ui.resize(w, h); 12 | figma.clientStorage 13 | .setAsync("figma-plugin-ui-size", { w: w, h: h }) 14 | .catch((err) => {}); // save size 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /figma-core/code-thread/show-ui.ts: -------------------------------------------------------------------------------- 1 | export async function showUI() { 2 | // communicates with ui.html 3 | // load plugin with confugured w/h 4 | // restore previous size 5 | 6 | let size: { w: number; h: number } = { w: 375, h: 667 }; 7 | try { 8 | const savedsize: { 9 | w: number; 10 | h: number; 11 | } = await figma.clientStorage.getAsync("figma-plugin-ui-size"); 12 | savedsize && (size = savedsize); 13 | } catch (_) {} 14 | 15 | figma.showUI(__html__, { width: size.w, height: size.h }); 16 | } 17 | -------------------------------------------------------------------------------- /figma-core/code-thread/user-interest.ts: -------------------------------------------------------------------------------- 1 | import { EK_SET_APP_MODE } from "@core/constant"; 2 | import { addEventHandler } from "./message-handler"; 3 | 4 | /** 5 | * [GLOBAL] current user viewing screen name 6 | */ 7 | export let user_interest: string; 8 | 9 | export function userInterestUnset(): boolean { 10 | return user_interest === undefined; 11 | } 12 | 13 | export function setUserInterest(interest: string) { 14 | console.log(`app mode set event recieved, now setting as "${user_interest}"`); 15 | user_interest = interest; 16 | } 17 | 18 | export function __register__() { 19 | addEventHandler(EK_SET_APP_MODE, (msg) => { 20 | setUserInterest(msg.data); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /figma-core/contents-extraction/README.md: -------------------------------------------------------------------------------- 1 | ## Extract contents / resources. 2 | 3 | 4 | - colors 5 | - texts 6 | - images 7 | - icons 8 | - text-styles 9 | - fonts 10 | - color 11 | - vector 12 | - properties 13 | - width 14 | - height 15 | - stroke width -------------------------------------------------------------------------------- /figma-core/event-handlers/README.md: -------------------------------------------------------------------------------- 1 | Look at init.ts 2 | -------------------------------------------------------------------------------- /figma-core/event-handlers/create-button.ts: -------------------------------------------------------------------------------- 1 | import { drawButtons } from "../reflect-render"; 2 | import { addEventHandler } from "../code-thread"; 3 | 4 | async function draw100000Buttons() { 5 | for (let i = 0; i < 1; i++) { 6 | await drawButtons(i); 7 | } 8 | } 9 | 10 | export function __register__() { 11 | addEventHandler("reflect-ui-generation/button-base", () => { 12 | draw100000Buttons(); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /figma-core/event-handlers/hide-all.ts: -------------------------------------------------------------------------------- 1 | import { hideAllExcept, hideAllOnly } from "../tool-box/manipulate"; 2 | import { addEventHandler, singleFigmaNodeSelection } from "../code-thread"; 3 | 4 | function hideAllExceptFromCurrentSelection( 5 | selection: SceneNode, 6 | except: NodeType 7 | ) { 8 | if (selection.type != "FRAME") { 9 | figma.notify("hide-all tools can be used only for framenode"); 10 | } else { 11 | hideAllExcept(selection, except); 12 | } 13 | } 14 | 15 | function hideAllOnlyFromCurrentSelection(selection: SceneNode, only: NodeType) { 16 | if (selection.type != "FRAME") { 17 | figma.notify("hide-all tools can be used only for framenode"); 18 | } else { 19 | hideAllOnly(selection, only); 20 | } 21 | } 22 | 23 | export function __register__() { 24 | addEventHandler("hide-all-except", (msg) => { 25 | hideAllExceptFromCurrentSelection( 26 | singleFigmaNodeSelection, 27 | msg.data.except 28 | ); 29 | }); 30 | addEventHandler("hide-all-only", (msg) => { 31 | hideAllOnlyFromCurrentSelection(singleFigmaNodeSelection, msg.data.only); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /figma-core/event-handlers/index.ts: -------------------------------------------------------------------------------- 1 | // DO NOT IMPORT ME UNLESS HOST IS CODE.TS 2 | 3 | /// 4 | /// simply importing this will register utility handlers. 5 | /// 6 | 7 | // index wrapper for importing init 8 | import "./init"; 9 | -------------------------------------------------------------------------------- /figma-core/event-handlers/init.ts: -------------------------------------------------------------------------------- 1 | import { __register__ as __register_create_icon__ } from "./create-icon"; 2 | import { __register__ as __register_create_image__ } from "./apply-image"; 3 | import { __register__ as __register_replace_text_characters__ } from "./apply-text-characters"; 4 | import { __register__ as __register_replace_font__ } from "./replace-font"; 5 | import { __register__ as __register_hide_all__ } from "./hide-all"; 6 | import { __register__ as __register_randomize_selection__ } from "./randomize-selection"; 7 | // 8 | __register_create_icon__(); 9 | __register_create_image__(); 10 | __register_replace_text_characters__(); 11 | __register_replace_font__(); 12 | __register_hide_all__(); 13 | __register_randomize_selection__(); 14 | 15 | // disabled for build size optimization. re-enable after migrating seed data on web side. 16 | // import { __register__ as __register_create_button__ } from "./create-button"; 17 | // __register_create_button__(); 18 | -------------------------------------------------------------------------------- /figma-core/event-handlers/randomize-selection.ts: -------------------------------------------------------------------------------- 1 | import { randimizeText } from "../tool-box/manipulate"; 2 | import { addEventHandler } from "../code-thread"; 3 | 4 | export function __register__() { 5 | addEventHandler("randomize-selection", () => { 6 | randimizeText(); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /figma-core/event-handlers/replace-font.ts: -------------------------------------------------------------------------------- 1 | import { EK_REPLACE_FONT } from "@core/constant"; 2 | import { replaceAllTextFontInFrame } from "../tool-box/manipulate"; 3 | import { addEventHandler, singleFigmaNodeSelection } from "../code-thread"; 4 | 5 | export function __register__() { 6 | addEventHandler(EK_REPLACE_FONT, async (msg) => { 7 | if (singleFigmaNodeSelection.type == "FRAME") { 8 | const font = "Roboto"; 9 | await replaceAllTextFontInFrame(singleFigmaNodeSelection, font); 10 | figma.notify(`successfuly changed font to ${font}`); 11 | } else { 12 | figma.notify("cannot replace font of non-frame node"); 13 | } 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /figma-core/node-cache/README.md: -------------------------------------------------------------------------------- 1 | # Node cache existing only on figma code thread. 2 | 3 | **for last selection** 4 | 5 | - Scene node (raw node) 6 | - Reflect node (converted node) 7 | -------------------------------------------------------------------------------- /figma-core/node-cache/memoize/README.md: -------------------------------------------------------------------------------- 1 | # Node calculation memoization repository. 2 | 3 | > Stores cache based on node complexity. e.g. for single layer, no memoization will be enabled. 4 | -------------------------------------------------------------------------------- /figma-core/node-cache/memoize/config.ts: -------------------------------------------------------------------------------- 1 | const _CACHE_TIME_OUT_MS = 700; 2 | 3 | export const DEFAULT_MEMOIZATION_CONFIG = { 4 | timeout: _CACHE_TIME_OUT_MS, 5 | complexity: 10, 6 | }; 7 | -------------------------------------------------------------------------------- /figma-core/node-cache/memoize/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./config"; 2 | -------------------------------------------------------------------------------- /figma-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "figma-core", 3 | "description": "Figma code thread shared package", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "main": "index.ts", 8 | "dependencies": { 9 | "@plugin-sdk/service": "*" 10 | }, 11 | "devDependencies": { 12 | "@figma/plugin-typings": "^1.58.0", 13 | "typescript": "^4.0.5" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /figma-core/physical-visual-store/README.md: -------------------------------------------------------------------------------- 1 | # Physical visual store 2 | 3 | This is a package for creating a physical & visual data node inside figma. this is designed for sync data between accounts and devices. 4 | 5 | > Since figma's `setPluginData` nor `setSharedPluginData` does not sync the data between clients. 6 | -------------------------------------------------------------------------------- /figma-core/physical-visual-store/checksum/is-managed-node.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * to keep data container node's name clean, we add the checksum container under it as a text's content. 3 | * @param node 4 | * @returns 5 | */ 6 | export function isManagedNodeByAssistant(node: BaseNode) { 7 | const jwt = checksum_container_name_inline_jwt(node.id); 8 | const regex = checksum_container_regex(jwt); 9 | if ("children" in node) { 10 | const checksum = node.findChildren( 11 | (c) => c.type === "TEXT" && RegExp(regex).test(c.characters) 12 | ); 13 | if (!checksum || checksum.length === 0) { 14 | return false; 15 | } 16 | } else { 17 | // node itself is a checksum container. this can only exist directly under page node. 18 | return RegExp(regex).test(node.name); 19 | } 20 | return true; 21 | } 22 | 23 | function checksum_container_name_inline_jwt(parent: string): string { 24 | // build checksum based on parent's id. 25 | return "--"; // TODO: 26 | } 27 | 28 | const checksum_container_regex = (jwt) => `/${jwt}/g`; 29 | -------------------------------------------------------------------------------- /figma-core/physical-visual-store/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./page-manager"; 2 | -------------------------------------------------------------------------------- /figma-core/physical-visual-store/page-manager/index.ts: -------------------------------------------------------------------------------- 1 | export { createPrimaryVisualStorePageIfNonExists as createPageIfNonExists } from "./craete-page-if-non-exist"; 2 | -------------------------------------------------------------------------------- /figma-core/physical-visual-store/used-emoji/README.md: -------------------------------------------------------------------------------- 1 | # Emojis are only used inside a visual store document. 2 | 3 | > Grida is not fan of a emoji. (well we do love to use them in a document, but we try our best to avoid them in our products design.) 4 | -------------------------------------------------------------------------------- /figma-core/physical-visual-store/used-emoji/index.ts: -------------------------------------------------------------------------------- 1 | const GEAR = "⚙"; // U+2699 2 | -------------------------------------------------------------------------------- /figma-core/platform-features/README.md: -------------------------------------------------------------------------------- 1 | # Figma platform specific features 2 | 3 | > most of this feature will be present on `@design-sdk/figma`, but assistant specific logics will be present here. 4 | -------------------------------------------------------------------------------- /figma-core/platform-features/file-checksum/README.md: -------------------------------------------------------------------------------- 1 | # Figma file checksum 2 | 3 | ## Why do we need this? 4 | 5 | There are two ways to access figma files. 6 | 7 | 1. via plugin api (assistant) 8 | 2. via http rest api (on other backend services) 9 | 10 | Grida uses both way to retreive, manage figma design. 11 | Since figma plugin api does not provide [filekey](https://www.figma.com/plugin-docs/api/figma/#filekey)(file id) for public plugins, we have to explicitly get input from user indicating the figma file id (which is both included in share link & node link.). after we do this, we have to save this file id on localstorage (pluginstorage) for later use cases. after user authenticates rather using assistant or other grida service, we'll ask user to authenticate figma oauth (so we can access it via http api), after we do this, we can now use saved file id as checksum and if the id can be trusted. 12 | 13 | Id is essential to keep track of design's version and changes. 14 | 15 | There is a open issue related to this issue. - [here (figma/plugin-typings#13)](https://github.com/figma/plugin-typings/issues/13) 16 | 17 | ## References 18 | 19 | - https://www.figma.com/plugin-docs/api/figma/#filekey 20 | -------------------------------------------------------------------------------- /figma-core/platform-features/file-checksum/api.ts: -------------------------------------------------------------------------------- 1 | /// checksum api 2 | /// backend is not ready. this is a dummy placeholder. 3 | 4 | import Axios, { AxiosInstance } from "axios"; 5 | 6 | let __client: AxiosInstance; // client chache 7 | 8 | const _client = async () => { 9 | if (__client) { 10 | return __client; 11 | } else { 12 | __client = Axios.create({ 13 | baseURL: "https://figma-link-service.grida.cc", 14 | headers: { 15 | Authorization: 16 | "Bearer " + (await figma.clientStorage.getAsync("access_token")), 17 | }, 18 | }); 19 | 20 | return __client; 21 | } 22 | }; 23 | 24 | export async function checksum(filedid: string): Promise { 25 | try { 26 | const res = await ( 27 | await _client() 28 | ).post("/file-checksum/validate", { 29 | fileid: filedid, 30 | }); 31 | 32 | return res.data.valid as boolean; 33 | } catch (error) { 34 | throw error; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /figma-core/platform-features/index.ts: -------------------------------------------------------------------------------- 1 | export * as file_checksum from "./file-checksum"; 2 | -------------------------------------------------------------------------------- /figma-core/reflect-render/README.md: -------------------------------------------------------------------------------- 1 | # Reflect Renderer for figma 2 | 3 | IN: reflect ui manifest. 4 | OUT: Draws ui on figma with exact same manifest. -------------------------------------------------------------------------------- /figma-core/reflect-render/icons.render/README.md: -------------------------------------------------------------------------------- 1 | ## references 2 | 3 | - https://github.com/google/material-design-icons 4 | - https://github.com/iconify/iconify-figma 5 | - https://www.figma.com/plugin-docs/api/VectorNode/ -------------------------------------------------------------------------------- /figma-core/reflect-render/index.ts: -------------------------------------------------------------------------------- 1 | export { drawButtons } from "./buttons.render" -------------------------------------------------------------------------------- /figma-core/reflect-render/textstyle.render/index.ts: -------------------------------------------------------------------------------- 1 | // TODO WIP 2 | export function createTextStyle(args: { 3 | name: string 4 | description?: string 5 | fontSize: number 6 | fontName: FontName 7 | }) { 8 | const style = figma.createTextStyle() 9 | style.fontName = args.fontName; 10 | style.fontSize = args.fontSize; 11 | style.name = args.name; 12 | style.description = args.description; 13 | } 14 | -------------------------------------------------------------------------------- /figma-core/relaunch-data/README.md: -------------------------------------------------------------------------------- 1 | # Relaunch data management 2 | 3 | ![](./relaunch-data-example.png) 4 | 5 | 1. initially, set the relaunce data on root page node for ux & plugin suggestion. 6 | 7 | ### References 8 | 9 | - https://www.figma.com/plugin-docs/api/properties/nodes-setrelaunchdata/ 10 | - https://www.figma.com/plugin-docs/manifest/#relaunchbuttons 11 | -------------------------------------------------------------------------------- /figma-core/relaunch-data/index.ts: -------------------------------------------------------------------------------- 1 | figma.once("run", () => { 2 | figma 3 | .getNodeById( 4 | /** 5 | * root node's id is always 0:0 on plugin api. [learn more](https://github.com/figma/plugin-typings/issues/13) 6 | */ 7 | "0:0" 8 | ) 9 | .setRelaunchData({ open: "" }); 10 | }); 11 | -------------------------------------------------------------------------------- /figma-core/relaunch-data/relaunch-data-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/figma-core/relaunch-data/relaunch-data-example.png -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/README.md: -------------------------------------------------------------------------------- 1 | ## Manipulation tool kits 2 | 3 | 4 | ### Reflect button maniuplation 5 | - manipulates all possible looks of buttons -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/font-replacer/README.md: -------------------------------------------------------------------------------- 1 | ## Font replacer 2 | 3 | ## HOW TO USE 4 | - select layers / screens (multiple) 5 | - choose fonts to be replaced. -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/font-replacer/index.ts: -------------------------------------------------------------------------------- 1 | export async function replaceAllTextFontInFrame(node: FrameNode, fontFamilly: string) { 2 | function convertChildren(children: ReadonlyArray) { 3 | children.forEach(async (c) => { 4 | if ('children' in c) { 5 | convertChildren(c.children) 6 | } 7 | if (c.type == "TEXT") { 8 | const font: FontName = { 9 | family: "Roboto", 10 | style: "Regular" 11 | } 12 | await figma.loadFontAsync(font); 13 | (c.fontName as FontName) = font 14 | } 15 | }) 16 | } 17 | 18 | convertChildren(node.children) 19 | } -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/hide-all/README.md: -------------------------------------------------------------------------------- 1 | # Hide all 2 | 3 | > Hides all node except X. -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/hide-all/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export function hideAllExcept(target: FrameNode | GroupNode | InstanceNode, except: NodeType) { 3 | target.children.forEach((n) => { 4 | if (n.type == "FRAME" || n.type == "GROUP" || n.type == "INSTANCE") { 5 | hideAllExcept(n, except); 6 | } else { 7 | if (n.type != except) { 8 | n.visible = false; 9 | } 10 | } 11 | }) 12 | } 13 | 14 | export function hideAllOnly(target: FrameNode | GroupNode | InstanceNode, only: NodeType) { 15 | target.children.forEach((n) => { 16 | if (n.type == "FRAME" || n.type == "GROUP" || n.type == "INSTANCE") { 17 | hideAllOnly(n, only); 18 | } else { 19 | if (n.type == only) { 20 | n.visible = false; 21 | } 22 | } 23 | }) 24 | } -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./font-replacer"; 2 | export * from "./hide-all"; 3 | export * from "./text-randomize"; 4 | -------------------------------------------------------------------------------- /figma-core/tool-box/manipulate/text-randomize/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * randomize the current selection of text 3 | * @todo - support other types. (currently only text supported) 4 | * @returns 5 | */ 6 | export async function randimizeText() { 7 | if (figma.currentPage.selection.length >= 2) { 8 | figma.notify("only single node randomize is supported"); 9 | return; 10 | } 11 | 12 | const primarySelection = figma.currentPage.selection[0]; 13 | if (primarySelection.type == "TEXT") { 14 | const text = primarySelection as TextNode; 15 | await figma.loadFontAsync(text.fontName as FontName); 16 | text.characters = 17 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices scelerisque leo nec consectetur. Sed porta metus molestie sollicitudin gravida. Nulla vitae metus sapien."; 18 | } 19 | if ( 20 | primarySelection.type == "RECTANGLE" || 21 | primarySelection.type == "ELLIPSE" 22 | ) { 23 | const box = primarySelection as RectangleNode; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /figma-core/tool-box/slot/README.md: -------------------------------------------------------------------------------- 1 | # Slot definition and management. 2 | 3 | 4 | *default dev-mode slot convention* 5 | - name should start with `"slot:"` in form of `"slot:slot-name"` 6 | - default name based supported variables are .. 7 | - text 8 | - text: string 9 | - image (on shape) 10 | - src: string 11 | - any 12 | - visible: boolean -------------------------------------------------------------------------------- /figma-native/.env.defaults: -------------------------------------------------------------------------------- 1 | # Optional 2 | FIGMA_PERSONAL_ACCESS_TOKEN=your-figma-access-token 3 | 4 | # No need to set - only required when contributing 5 | BRIDGED_FIRST_PARTY_ANALYTICS_PROXY_SERVICE_TOTP_SECRET=00000000 6 | 7 | # No need to set - only required when contributing 8 | GRIDA_FIRST_PARTY_PROXY_AUTH_REQUEST_TOTP_SECRET=00000000 -------------------------------------------------------------------------------- /figma-native/README.md: -------------------------------------------------------------------------------- 1 | # Figma Native - A non-web-hosted version of figma plugin. 2 | 3 | This runs everything within only figma host. even webpages are served internally, not via localhost; 4 | 5 | Using this will overload plugin booting time & interaction delay 6 | -------------------------------------------------------------------------------- /figma-native/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Grida (Heavy)", 3 | "id": "1009859297533324545", 4 | "api": "1.0.0", 5 | "main": "dist/code.js", 6 | "ui": "dist/ui.html", 7 | "editorType": [ 8 | "figma" 9 | ] 10 | } -------------------------------------------------------------------------------- /figma-native/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "figma-native", 3 | "version": "2021.0.1f1.1", 4 | "keywords": [ 5 | "figma", 6 | "bridged", 7 | "flutter", 8 | "flutter-figma", 9 | "figma-plugin" 10 | ], 11 | "license": "https://github.com/bridgedxyz/contributing-and-license", 12 | "author": "bridged.xyz by softmarshmallow ", 13 | "dependencies": { 14 | "app": "*", 15 | "figma-js": "^1.13.0", 16 | "figma-core": "*" 17 | }, 18 | "scripts": { 19 | "webpack:watch": "webpack --watch", 20 | "build": "webpack -p --mode=production", 21 | "dev": "webpack --watch" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /figma-native/src/code.ts: -------------------------------------------------------------------------------- 1 | import "figma-core"; 2 | -------------------------------------------------------------------------------- /figma-native/src/ui.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import App from "app/lib/main"; 3 | import { TargetPlatform } from "@plugin-sdk/core"; 4 | import * as ReactDOM from "react-dom"; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById("react-page") 9 | ); 10 | -------------------------------------------------------------------------------- /figma-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "lib": ["es2019", "es2017", "es7", "es6", "dom", "dom.iterable"], 6 | "jsx": "react", 7 | "esModuleInterop": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "allowSyntheticDefaultImports": true, 11 | "sourceMap": true, 12 | "experimentalDecorators": true, 13 | "noUnusedLocals": false, 14 | "typeRoots": [ 15 | "./node_modules/@types", 16 | "../node_modules/@types", 17 | "../node_modules/@figma" 18 | ] 19 | }, 20 | "exclude": ["node_modules", "dist", "example", "tests"] 21 | } 22 | -------------------------------------------------------------------------------- /figma/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *-archive.zip -------------------------------------------------------------------------------- /figma/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to assistant figma platform 2 | 3 | ## Setting up Env vars (.env) 4 | 5 | > In most case, you won't have to specify contents or create `figma/.env` file. 6 | 7 | **Variables** 8 | 9 | - `FIGMA_PERSONAL_ACCESS_TOKEN` - (Optional) For using figma developer tools. 10 | - `BRIDGED_FIRST_PARTY_APP_TOTP_SECRET` - (Not Required) Used for communicating with bridged first party cloud services. set this as "s1v1-assistant-development". learn more at [base's security startegy](https://github.com/gridaco/base/blob/main/docs/security.md) 11 | 12 | ## Good to know - Somethings leart from mistakes 13 | 14 | - figma's node does return property until they are referenced 15 | 16 | ## Clearing the cache 17 | 18 | Clearing the cache to work with figma plugin api storage. on MacOS, 19 | 20 | ```sh 21 | rm -rf "$HOME/Library/Application Support/Figma/"{Desktop,DesktopProfile} 22 | ``` 23 | -------------------------------------------------------------------------------- /figma/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Grida", 3 | "id": "896445082033423994", 4 | "api": "1.0.0", 5 | "main": "dist/code.js", 6 | "ui": "dist/ui.html", 7 | "editorType": [ 8 | "figma" 9 | ], 10 | "relaunchButtons": [ 11 | { 12 | "command": "open", 13 | "name": "Open Assistant", 14 | "multipleSelection": true 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /figma/scripts/optimize.js: -------------------------------------------------------------------------------- 1 | // before publishing update to figma, clean the dist forder for the size reduction. 2 | // leave only dist/code.js and dist/ui.js under the dist folder (remove all other files) 3 | 4 | const fs = require("fs"); 5 | const path = require("path"); 6 | 7 | const distPath = path.join(__dirname, "../dist"); 8 | 9 | fs.readdirSync(distPath).forEach((file) => { 10 | if (file !== "code.js" && file !== "ui.html") { 11 | fs.unlink(path.join(distPath, file), (err) => { 12 | if (err) throw err; 13 | }); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /figma/src/code.ts: -------------------------------------------------------------------------------- 1 | import "figma-core"; 2 | -------------------------------------------------------------------------------- /figma/src/handle-proxy-requests.ts: -------------------------------------------------------------------------------- 1 | import { 2 | TransportPluginEvent, 3 | PLUGIN_SDK_EK_BROWSER_OPEN_URI, 4 | } from "@plugin-sdk/core"; 5 | 6 | export function handle(payload: TransportPluginEvent) { 7 | console.log("handling proxy request from hosted app.", payload); 8 | if (payload.key == PLUGIN_SDK_EK_BROWSER_OPEN_URI) { 9 | open(payload.data.uri); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /figma/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "lib": ["es2019", "es2017", "es7", "es6", "dom", "dom.iterable"], 6 | "jsx": "react", 7 | "resolveJsonModule": true, 8 | "esModuleInterop": true, 9 | "outDir": "dist", 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "noUnusedLocals": false, 13 | "typeRoots": [ 14 | "./node_modules/@types", 15 | "../node_modules/@types", 16 | "../node_modules/@figma" 17 | ], 18 | "declaration": true, 19 | "sourceMap": true 20 | }, 21 | "exclude": ["node_modules", "dist", "example", "tests"] 22 | } 23 | -------------------------------------------------------------------------------- /figma/tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": false, 5 | "sourceMap": false, 6 | "removeComments": true 7 | }, 8 | "exclude": ["node_modules", "dist", "example", "tests"] 9 | } 10 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module assistant 2 | 3 | go 1.16 4 | 5 | require github.com/flutter/flutter v1.16.3 // indirect 6 | -------------------------------------------------------------------------------- /packages/README.md: -------------------------------------------------------------------------------- 1 | ## sub packages directory. 2 | 3 | > the modules imprted, [flutter-builder](https://github.com/bridgedxyz/flutter-builder), and [lint](https://github.com/bridgedxyz/lint) are git submodules, please visit theirs repository to contribute on sub modules. 4 | 5 | ### Packages 6 | 7 | - lint 8 | - box 9 | - flutter-builder 10 | - web-builder 11 | - design-plugins-sdk 12 | 13 | ## The naming 14 | 15 | - @app - app related logics & ui 16 | - @core - logics only 17 | - @toolbox - like @app, contains logics & ui, but in a micro way (features that are unlikely to be primarily used) 18 | - @ui - ui related / shared components 19 | -------------------------------------------------------------------------------- /packages/_firstparty-analytics/README.md: -------------------------------------------------------------------------------- 1 | # Assistant analytics module 2 | 3 | ## Data we collect 4 | 5 | **Events** 6 | 7 | - page_view - a general anonymous page view data 8 | - select_node - a general node selection event 9 | 10 | **Feature usage** 11 | 12 | - code genration from `features/design-to-code` 13 | - icon load from `features/icons-loader` 14 | 15 | **Statistics** 16 | 17 | - document statistics 18 | - pages count 19 | - components count 20 | - screens count 21 | -------------------------------------------------------------------------------- /packages/_firstparty-analytics/index.ts: -------------------------------------------------------------------------------- 1 | import { assistant as analytics } from "@analytics.bridged.xyz/internal"; 2 | 3 | export function initialize() { 4 | if (process.env.NODE_ENV == "production") { 5 | // init & hit page view 6 | // we yet do not track client id, every session is anonymous. 7 | // const client_id = nanoid(); 8 | // with proxy 9 | analytics.initWithProxy( 10 | process.env.BRIDGED_FIRST_PARTY_ANALYTICS_PROXY_SERVICE_TOTP_SECRET ?? 11 | process.env 12 | .NEXT_PUBLIC_BRIDGED_FIRST_PARTY_ANALYTICS_PROXY_SERVICE_TOTP_SECRET 13 | ); 14 | 15 | // Emmit login event to mock user. (since user authentication is optional to initially use assistant.) 16 | analytics.event({ 17 | name: "login", 18 | params: { 19 | method: "anonymous", 20 | }, 21 | }); 22 | 23 | // TODO - chagne with current page 24 | analytics.event_page_view("code"); 25 | } else { 26 | console.log( 27 | "[ASSITANT] using development build. ignoring analytics feature." 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/_firstparty-analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assistant-fp/analytics", 3 | "description": "First party analytics for assistant", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "dependencies": {} 7 | } -------------------------------------------------------------------------------- /packages/_firstparty-auth/README.md: -------------------------------------------------------------------------------- 1 | # First pary auth - do not modify under this directory unless you are a inside collaborator. 2 | 3 | > Cases for general contributing, you won't have to modify files under this directory. 4 | -------------------------------------------------------------------------------- /packages/_firstparty-auth/no-auth-trial-manager.ts: -------------------------------------------------------------------------------- 1 | //// 2 | //// Manage the quota of app usage as on unauthenticated anonymous user. 3 | //// 4 | 5 | import { PluginSdk } from "@plugin-sdk/app"; 6 | 7 | const _STATE_STORE_KEY = "trial-state-store-key"; 8 | export class TrialManager { 9 | private static _instance: TrialManager; 10 | private state; 11 | public static get instance(): TrialManager { 12 | if (!TrialManager._instance) { 13 | TrialManager._instance = new TrialManager(); 14 | } 15 | return TrialManager._instance; 16 | } 17 | 18 | private constructor() { 19 | this._loadstate(); 20 | } 21 | 22 | async _loadstate() { 23 | if (!this.state) { 24 | this.state = await PluginSdk.getItem(_STATE_STORE_KEY); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/_firstparty-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assistant-fp/auth", 3 | "description": "First party authentication for assistant", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "dependencies": {} 7 | } -------------------------------------------------------------------------------- /packages/_firstparty-auth/storage.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | import { PluginSdk } from "@plugin-sdk/app"; 5 | 6 | /** Preserve value: Do not change value */ 7 | const _ASSISTANT_GRIDA_AUTHENTICATION_CREDENTIAL_KEY = 8 | "co.grida.assistant/user-auth"; 9 | 10 | type Credential = string; 11 | 12 | function saveAuthCredential(credential: Credential) { 13 | PluginSdk.setItem(_ASSISTANT_GRIDA_AUTHENTICATION_CREDENTIAL_KEY, credential); 14 | } 15 | 16 | async function getAuthCredential(): Promise { 17 | return PluginSdk.getItem(_ASSISTANT_GRIDA_AUTHENTICATION_CREDENTIAL_KEY); 18 | } 19 | 20 | function saveProfile(profile) { 21 | // usees localstorage 22 | window.localStorage.setItem("my-profile", JSON.stringify(profile)); 23 | } 24 | 25 | function getProfile() { 26 | // usees localstorage 27 | return JSON.parse(window.localStorage.getItem("my-profile")); 28 | } 29 | 30 | export const AuthStorage = { 31 | save: saveAuthCredential, 32 | saveProfile: saveProfile, 33 | get: getAuthCredential, 34 | getProfile: getProfile, 35 | }; 36 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/guards/index.ts: -------------------------------------------------------------------------------- 1 | import { useEarlyAccess } from "@assistant-fp/early-access"; 2 | import { useHistory } from "react-router-dom"; 3 | import { early_access_required_message } from "../k"; 4 | 5 | export function requiresEarlyAccess(f: T): T { 6 | const history = useHistory(); 7 | const ea = useEarlyAccess(); 8 | 9 | if (!ea) { 10 | return ((...args) => { 11 | alert(early_access_required_message); 12 | history.push("/upgrade"); 13 | }) as any as T; 14 | } else { 15 | return f; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./use-early-access"; 2 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/hooks/use-early-access.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import store from "../store"; 3 | 4 | export function useEarlyAccess() { 5 | const [accesskey, setAccessKey] = useState(null); 6 | useEffect(() => { 7 | store.get().then((d) => { 8 | if (d) { 9 | setAccessKey(d); 10 | } 11 | }); 12 | }, []); 13 | 14 | return accesskey; 15 | } 16 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/index.ts: -------------------------------------------------------------------------------- 1 | export { UpgradePage } from "./register"; 2 | export * from "./guards"; 3 | export * from "./hooks"; 4 | export { default as store } from "./store"; 5 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/k.ts: -------------------------------------------------------------------------------- 1 | export const __key = "assistant-early-access-activation"; 2 | export const early_access_required_message = 3 | "This is a pro feature, please activate"; 4 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assistant-fp/early-access", 3 | "version": "0.0.0", 4 | "license": "MIT" 5 | } 6 | -------------------------------------------------------------------------------- /packages/_firstparty-early-access/store.ts: -------------------------------------------------------------------------------- 1 | import { __key } from "./k"; 2 | import { PluginSdk } from "@plugin-sdk/app"; 3 | 4 | const store = { 5 | set: (value: any) => { 6 | return PluginSdk.setItem(__key, value); 7 | }, 8 | get: async () => { 9 | return await PluginSdk.getItem(__key); 10 | }, 11 | }; 12 | 13 | export default store; 14 | -------------------------------------------------------------------------------- /packages/_logger/index.ts: -------------------------------------------------------------------------------- 1 | export class Logger { 2 | constructor(readonly namespace: string) {} 3 | 4 | /** 5 | * log sequence 6 | */ 7 | log_s() { 8 | throw "not implemnted"; 9 | } 10 | static debug(message?: any, ...optionalParams: any[]) { 11 | if (process.env.NODE_ENV == "development") { 12 | console.log(message, optionalParams); 13 | } 14 | } 15 | static info(message?: any, ...optionalParams: any[]) { 16 | console.info(message, optionalParams); 17 | } 18 | static warn(message?: any, ...optionalParams: any[]) { 19 | console.warn(message, optionalParams); 20 | } 21 | static error(message?: any, ...optionalParams: any[]) { 22 | console.error(message, optionalParams); 23 | } 24 | static log(message?: any, ...optionalParams: any[]) { 25 | console.log(message, optionalParams); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/_logger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logger", 3 | "description": "custom logger", 4 | "authors": "Grida co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": {} 8 | } -------------------------------------------------------------------------------- /packages/_utils/debounce.ts: -------------------------------------------------------------------------------- 1 | export function debounce( 2 | func: T, 3 | wait: number = 50, 4 | immediate?: boolean 5 | ) { 6 | var timeout; 7 | return function () { 8 | // @ts-ignore 9 | var context = this, 10 | args = arguments; 11 | var later = function () { 12 | if (!immediate) func.apply(context, args); 13 | }; 14 | var callNow = immediate && !timeout; 15 | clearTimeout(timeout); 16 | timeout = setTimeout(later, wait); 17 | if (callNow) func.apply(context, args); 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /packages/_utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/utils", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/app-auth/index.ts: -------------------------------------------------------------------------------- 1 | export { SigninScreen } from "./signin/signin-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/auth", 3 | "version": "0.0.0", 4 | "description": "First pary auth - UI only container", 5 | "private": false 6 | } -------------------------------------------------------------------------------- /packages/app-component-manage/index.ts: -------------------------------------------------------------------------------- 1 | export { ComponentViewScreen } from "./component-view-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-component-manage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/component-manage", 3 | "description": "description", 4 | "authors": "author", 5 | "version": "0.0.0", 6 | "dependencies": {} 7 | } -------------------------------------------------------------------------------- /packages/app-component-manage/schema-editor.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { SchemaEditor } from "@app/schema-editor"; 3 | 4 | export function ComponentSchemaEditor() { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /packages/app-copywriter/client/index.ts: -------------------------------------------------------------------------------- 1 | import Axios from "axios"; 2 | 3 | const client = Axios.create({ 4 | baseURL: "/api", 5 | }); 6 | 7 | interface TextResponse { 8 | q: string; 9 | texts: string[]; 10 | model: string; 11 | } 12 | 13 | interface TextPrompt { 14 | q: string; 15 | } 16 | 17 | export async function prompt(p: TextPrompt): Promise { 18 | const { data } = await client.get("/generative/texts", { 19 | params: p, 20 | }); 21 | 22 | return data; 23 | } 24 | -------------------------------------------------------------------------------- /packages/app-copywriter/components/bubble.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | 4 | export function Bubble({ 5 | onClick, 6 | children, 7 | }: React.PropsWithChildren<{ 8 | onClick?: () => void; 9 | }>) { 10 | return {children}; 11 | } 12 | 13 | const BubbleWrapper = styled.div` 14 | cursor: pointer; 15 | display: flex; 16 | flex-direction: column; 17 | padding: 21px; 18 | background: rgba(0, 0, 0, 0.02); 19 | border-radius: 8px; 20 | 21 | p { 22 | margin: 0; 23 | font-size: 16px; 24 | color: rgba(0, 0, 0, 0.8); 25 | } 26 | `; 27 | -------------------------------------------------------------------------------- /packages/app-copywriter/components/group-label.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export function GroupLabel({ 4 | children, 5 | style = {}, 6 | }: React.PropsWithChildren<{ 7 | style?: React.CSSProperties; 8 | }>) { 9 | return ( 10 |
21 | {children} 22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /packages/app-copywriter/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bubble"; 2 | export * from "./group-label"; 3 | export * from "./prompt-input-box"; 4 | -------------------------------------------------------------------------------- /packages/app-copywriter/index.ts: -------------------------------------------------------------------------------- 1 | export { CopywriterScreen } from "./copywriter"; 2 | -------------------------------------------------------------------------------- /packages/app-copywriter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/copywriter", 3 | "version": "0.0.0", 4 | "private": false, 5 | "license": "MIT", 6 | "dependencies": { 7 | "react-textarea-autosize": "^8.4.0" 8 | }, 9 | "peerDependencies": { 10 | "react": "^18.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/app-data-mapper/README.md: -------------------------------------------------------------------------------- 1 | # Data mapper 2 | 3 | - data schema design 4 | - load data into view 5 | - dump data from view 6 | 7 | ## How to use 8 | 9 | select the target node and datasource node, click sync. 10 | -------------------------------------------------------------------------------- /packages/app-data-mapper/__plugin/events.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | import { PluginSdkService } from "@plugin-sdk/service"; 3 | 4 | const EVKEY = "data-mapper-custom-transport"; 5 | export interface _Event_DataMapper_GoodUserInputTransfer { 6 | sourceNodeId: string; 7 | targetNodesId: string[]; 8 | } 9 | 10 | export function fromApp(data: _Event_DataMapper_GoodUserInputTransfer) { 11 | PluginSdk.appEvent(EVKEY, data); 12 | } 13 | 14 | export function onService( 15 | cb: (data: _Event_DataMapper_GoodUserInputTransfer) => void 16 | ) { 17 | PluginSdkService.onAppReqquest(EVKEY, cb); 18 | } 19 | -------------------------------------------------------------------------------- /packages/app-data-mapper/example-data-source.ts: -------------------------------------------------------------------------------- 1 | const __ExampleComponentDataSource = require("./mock-data-example.json"); 2 | 3 | type ImageUri = string; 4 | type ImageBase64 = string; 5 | type ImageString = ImageUri | ImageBase64; 6 | type EmailString = string; 7 | 8 | export interface __ExampleComponentProps { 9 | title: string; 10 | description: string; 11 | email: EmailString; 12 | avatar: ImageString; 13 | } 14 | 15 | export class ExampleDataMapperMockDataSource { 16 | rowsCount: number; 17 | data: T[]; 18 | 19 | constructor() { 20 | this.data = __ExampleComponentDataSource; 21 | this.rowsCount = this.data.length; 22 | } 23 | 24 | getSingleRandom(): T { 25 | return getrandom(this.data); 26 | } 27 | } 28 | 29 | function getrandom(items: T[]): T { 30 | const item = items[Math.floor(Math.random() * items.length)]; 31 | return item; 32 | } 33 | -------------------------------------------------------------------------------- /packages/app-data-mapper/index.ts: -------------------------------------------------------------------------------- 1 | export { DataMapperScreen } from "./data-mapper-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-data-mapper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/data-mapper", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/app-design-lint/README.md: -------------------------------------------------------------------------------- 1 | # Lint related components & logics 2 | 3 | > General Shared components will be placed under /components. only lint-specific-related components shall be placed under this directory. 4 | -------------------------------------------------------------------------------- /packages/app-design-lint/__plugin/events.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | import { PluginSdkService } from "@plugin-sdk/service"; 3 | 4 | const EVKEY = "lint-runner-custom-transport"; 5 | export const _APP_EVENT_LINT_RESULT_EK = "lint-result"; 6 | export interface LintRequest { 7 | type: "lint-request"; 8 | } 9 | 10 | export type _Lint_Event = LintRequest; 11 | 12 | export function fromApp(data: _Lint_Event) { 13 | PluginSdk.appEvent(EVKEY, data); 14 | } 15 | 16 | export function onService(cb: (data: _Lint_Event) => void) { 17 | PluginSdkService.onAppReqquest(EVKEY, cb); 18 | } 19 | -------------------------------------------------------------------------------- /packages/app-design-lint/__plugin/index.ts: -------------------------------------------------------------------------------- 1 | import { onService, _Lint_Event, _APP_EVENT_LINT_RESULT_EK } from "./events"; 2 | import { runLints } from "@designto/clean"; 3 | import { FigmaNodeCache } from "figma-core/node-cache"; 4 | 5 | onService(main_cb); 6 | 7 | // main callback 8 | function main_cb(evt: _Lint_Event) { 9 | // to logic 10 | 11 | switch (evt.type) { 12 | case "lint-request": 13 | _handle_lint_request(); 14 | break; 15 | } 16 | } 17 | 18 | function _handle_lint_request() { 19 | //#region run linter 20 | const rnode = FigmaNodeCache.getLastConverted(); 21 | if (rnode) { 22 | try { 23 | const feedbacks = runLints(rnode); 24 | console.info("feedbacks:", feedbacks); 25 | figma.ui.postMessage({ 26 | type: _APP_EVENT_LINT_RESULT_EK, 27 | data: feedbacks, 28 | }); 29 | } catch (e) { 30 | console.error(e); 31 | } 32 | } else { 33 | console.warn("user requested linting, but non selected to run lint on."); 34 | } 35 | //#endregion 36 | } 37 | -------------------------------------------------------------------------------- /packages/app-design-lint/group-by/README.md: -------------------------------------------------------------------------------- 1 | # Lint group by logics 2 | 3 | - 1. group by errors 4 | - 2. group by none - all as list 5 | -------------------------------------------------------------------------------- /packages/app-design-lint/group-by/index.ts: -------------------------------------------------------------------------------- 1 | // TODO: 2 | -------------------------------------------------------------------------------- /packages/app-design-lint/hooks/README.md: -------------------------------------------------------------------------------- 1 | # Lint related hooks 2 | -------------------------------------------------------------------------------- /packages/app-design-lint/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./lint-screen"; 2 | export * from "./lint-item-row"; 3 | export * from "./lint-tree-view"; 4 | export * from "./lint-level-indicator"; 5 | -------------------------------------------------------------------------------- /packages/app-design-lint/lint-colors.ts: -------------------------------------------------------------------------------- 1 | export enum Level { 2 | warn = "warning", 3 | error = "error", 4 | none = "none", 5 | ignore = "ignore", 6 | todo = "todo", 7 | } 8 | -------------------------------------------------------------------------------- /packages/app-design-lint/lint-error-icon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import ColorErrorIcon from "@assistant/lint-icons/error-missing-color-style"; 3 | import TextStyleErrorIcon from "@assistant/lint-icons/error-missing-text-style"; 4 | import NamingErrorIcon from "@assistant/lint-icons/error-missing-text-style"; 5 | 6 | export enum LintError { 7 | text = "missingTextStyle", 8 | name = "nameError", 9 | color = "missingColorStyleError", 10 | } 11 | 12 | interface Props { 13 | id?: string; 14 | } 15 | 16 | export function LintErrorIcon(props: Props) { 17 | switch (props.id) { 18 | case LintError.text: 19 | return ; 20 | case LintError.name: 21 | return ; 22 | case LintError.color: 23 | return ; 24 | default: 25 | return <>; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/app-design-lint/lint-item-row/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./lint-item-row" -------------------------------------------------------------------------------- /packages/app-design-lint/lint-level-indicator.tsx: -------------------------------------------------------------------------------- 1 | import { css } from "@emotion/react"; 2 | import styled from "@emotion/styled"; 3 | import * as React from "react"; 4 | import { Level } from "./lint-colors"; 5 | 6 | interface ILintLevelIndicator { 7 | color: string; 8 | } 9 | 10 | export function LintLevelIndicator(props: ILintLevelIndicator) { 11 | return ; 12 | } 13 | 14 | interface IIndicator { 15 | color: string; 16 | } 17 | 18 | const Indicator = styled.div` 19 | width: 8px; 20 | height: 8px; 21 | border-radius: 50%; 22 | 23 | ${(props) => 24 | props.color == Level.warn 25 | ? css` 26 | background: #ffc700; 27 | ` 28 | : props.color == Level.error 29 | ? css` 30 | background: #ff3a3a; 31 | ` 32 | : props.color == Level.ignore 33 | ? css` 34 | background: #c6c6c6; 35 | ` 36 | : props.color == Level.todo 37 | ? css` 38 | background: #000; 39 | ` 40 | : css` 41 | background: #fff; 42 | `}; 43 | `; 44 | -------------------------------------------------------------------------------- /packages/app-design-lint/lint-list-view/index.tsx: -------------------------------------------------------------------------------- 1 | /** @deprecated this is dummy. replace me */ 2 | export const dummy = "dummy"; 3 | 4 | export const choiceItem = { 5 | selected: false, 6 | choice: { 7 | title: "choice 1", 8 | explanation: "I’ll choose this option to resolve this issue.", 9 | }, 10 | }; 11 | 12 | export const rowDummy = { 13 | onTap: function T() { 14 | // FIXME: here is setState 15 | }, 16 | name: "hi", 17 | icon: "missingTextStyle", 18 | expand: false, // FIXME: here is state 19 | level: "warning", 20 | error: { 21 | id: "id", 22 | name: "Error name", 23 | userMessage: "This error is caused by “layer-name” and needs to be fixed.", 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /packages/app-design-lint/lint-tree-view/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./lint-tree-view"; 2 | -------------------------------------------------------------------------------- /packages/app-design-lint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/design-lint", 3 | "description": "design linter related package", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": {} 8 | } -------------------------------------------------------------------------------- /packages/app-design-preview/components/fullscreen-appbar-action-button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | 4 | export function FullscreenAppbarActionButton({ 5 | onClick, 6 | children, 7 | disabled, 8 | title, 9 | }: { 10 | onClick?: () => void; 11 | children: React.ReactNode; 12 | disabled?: boolean; 13 | title?: string; 14 | }) { 15 | return ( 16 | 19 | ); 20 | } 21 | 22 | const Button = styled.button` 23 | background-color: rgb(236, 236, 236); 24 | border-radius: 4px; 25 | padding: 8px 10px; 26 | color: rgb(115, 115, 115); 27 | font-size: 12px; 28 | font-family: "Helvetica Neue", sans-serif; 29 | font-weight: 500; 30 | border: none; 31 | outline: none; 32 | cursor: pointer; 33 | 34 | :hover { 35 | opacity: 0.8; 36 | } 37 | 38 | :disabled { 39 | opacity: 0.5; 40 | cursor: not-allowed; 41 | } 42 | 43 | :active { 44 | opacity: 1; 45 | } 46 | 47 | :focus { 48 | } 49 | `; 50 | -------------------------------------------------------------------------------- /packages/app-design-preview/components/index.ts: -------------------------------------------------------------------------------- 1 | export { FullscreenAppbarActionButton } from "./fullscreen-appbar-action-button"; 2 | -------------------------------------------------------------------------------- /packages/app-design-preview/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./preview-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-design-preview/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/design-preview", 3 | "description": "design previewer", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": {} 8 | } -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/README.md: -------------------------------------------------------------------------------- 1 | # code syntax highligher for design 2 | 3 | ## Disclaimer 4 | 5 | > This package was initiated from https://github.com/ixtgorilla/figma-code-highlighter 6 | 7 | Under `BSD-3` 8 | 9 | ## About Highlight js. 10 | 11 | do not upgrade hightlight.js version - it won't run for figma. current tested version is `9.15.10` 12 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/__plugin/event.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdkService } from "@plugin-sdk/service"; 2 | import { PluginSdk } from "@plugin-sdk/app"; 3 | import { SchemaAndLanguage } from "../models"; 4 | 5 | const EVKEY = "highligter"; 6 | const CHANGE_COLOR_REQUEST_KEY = "CHANGE_COLOR"; 7 | 8 | export interface HighlightEvent { 9 | type: typeof CHANGE_COLOR_REQUEST_KEY; 10 | schemaAndLanguage: SchemaAndLanguage; 11 | } 12 | 13 | export function fromApp(data: HighlightEvent) { 14 | PluginSdk.appEvent(EVKEY, data); 15 | } 16 | 17 | export function onService(cb: (data: HighlightEvent) => void) { 18 | PluginSdkService.onAppReqquest(EVKEY, cb); 19 | } 20 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/__plugin/index.ts: -------------------------------------------------------------------------------- 1 | import { SchemaAndLanguage } from "../models/schema-and-language"; 2 | import changeColorUsecase from "./change-color-usecase"; 3 | import { HighlightEvent, onService } from "./event"; 4 | 5 | onService(main_cb); 6 | 7 | // main callback 8 | function main_cb(evt: HighlightEvent) { 9 | if (evt.type == "CHANGE_COLOR") { 10 | const schemaAndLanguage: SchemaAndLanguage = evt.schemaAndLanguage; 11 | 12 | try { 13 | figma.currentPage.selection && 14 | changeColorUsecase(figma.currentPage.selection, schemaAndLanguage); 15 | } catch (e) { 16 | console.error(e); 17 | figma.notify(`😭 ${e}`); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/design-text-code-syntax-highligh-screen.css: -------------------------------------------------------------------------------- 1 | .box { 2 | margin: 8px 0 16px; 3 | } 4 | 5 | .flex { 6 | display: flex; 7 | padding-bottom: 8px; 8 | } 9 | 10 | .flexChild:first-child { 11 | width: 50%; 12 | padding-right: 4px; 13 | } 14 | 15 | .flexChild:last-child { 16 | width: 50%; 17 | padding-left: 4px; 18 | } 19 | 20 | .boxPadding { 21 | padding: 16px 0; 22 | } 23 | 24 | .cursor { 25 | cursor: pointer; 26 | } 27 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/index.ts: -------------------------------------------------------------------------------- 1 | export { DesignTextCdoeSyntaxHighligherScreen } from "./design-text-code-syntax-highligh-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/language/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./language-list"; 2 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./schema-and-language"; 2 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/models/schema-and-language.ts: -------------------------------------------------------------------------------- 1 | export interface SchemaAndLanguage { 2 | language: string; 3 | colorSchema: string; 4 | } 5 | 6 | export type FavoriteBookmarks = SchemaAndLanguage[]; 7 | export type CurrentPreference = SchemaAndLanguage; 8 | -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/design-text-code-syntax-highlight", 3 | "version": "0.0.0", 4 | "description": "code syntax highlighter for design texts", 5 | "private": false, 6 | "license": "BSD-3-Clause", 7 | "dependencies": { 8 | "highlight.js": "9.15.10", 9 | "xmldom": "^0.6.0", 10 | "xpath": "^0.0.32" 11 | }, 12 | "devDependencies": { 13 | "@types/highlight.js": "9.12.3" 14 | } 15 | } -------------------------------------------------------------------------------- /packages/app-design-text-code-syntax-hightlight/preferences/index.ts: -------------------------------------------------------------------------------- 1 | import { SchemaAndLanguage, FavoriteBookmarks } from "../models"; 2 | import { PluginSdk } from "@plugin-sdk/app"; 3 | 4 | const current_schema_and_language_setting_key = 5 | "highlighter/current-schema-and-language"; 6 | const bookmarks_store_key = "highlighter/favorite-settings-bookmark"; 7 | 8 | export async function get_syntax_highlight_preferences() { 9 | return await PluginSdk.getItem( 10 | current_schema_and_language_setting_key 11 | ); 12 | } 13 | 14 | export async function set_syntax_highlight_preferences(d: SchemaAndLanguage) { 15 | return await PluginSdk.setItem( 16 | current_schema_and_language_setting_key, 17 | d 18 | ); 19 | } 20 | 21 | export async function get_favorite_bookmarks() { 22 | return await PluginSdk.getItem(bookmarks_store_key); 23 | } 24 | 25 | export function set_favorite_bookmarks(l: FavoriteBookmarks) { 26 | PluginSdk.setItem(bookmarks_store_key, l); 27 | } 28 | -------------------------------------------------------------------------------- /packages/app-design-to-code/__plugin/events.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | import { PluginSdkService } from "@plugin-sdk/service"; 3 | import { FrameworkOption } from "../framework-option"; 4 | 5 | const EVKEY = "design-to-code-preview-custom-transport"; 6 | export const _APP_EVENT_CODE_GEN_RESULT_EK = "design-to-code-result"; 7 | export interface CodeGenRequest { 8 | type: "code-gen-request"; 9 | option: FrameworkOption; 10 | config: { 11 | do_generate_vanilla_preview_source: boolean; 12 | }; 13 | } 14 | 15 | export type _Code_Event = CodeGenRequest; 16 | 17 | export function fromApp(data: _Code_Event) { 18 | PluginSdk.appEvent(EVKEY, data); 19 | } 20 | 21 | export function onService(cb: (data: _Code_Event) => void) { 22 | PluginSdkService.onAppReqquest(EVKEY, cb); 23 | } 24 | -------------------------------------------------------------------------------- /packages/app-design-to-code/code-session-cache-storage.ts: -------------------------------------------------------------------------------- 1 | import { DesigntoCodeUserOptions } from "./user-options"; 2 | 3 | export class CodeSessionCacheStorage { 4 | private readonly key; 5 | constructor( 6 | readonly node: string, 7 | readonly preference: DesigntoCodeUserOptions 8 | ) { 9 | if (!node || !preference) { 10 | // both required 11 | this.key = null; 12 | } else { 13 | this.key = `${node}-${preference?.framework}-${preference?.language}`; 14 | } 15 | } 16 | 17 | setCache(code: string) { 18 | if (this.key) { 19 | window.localStorage.setItem(this.key, code); 20 | } 21 | } 22 | 23 | getCache(): string | null { 24 | if (this.key) { 25 | return window.localStorage.getItem(this.key); 26 | } 27 | // using null return since localstorage return is also optional 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/app-design-to-code/footer-action/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/app-design-to-code/footer-action/index.ts -------------------------------------------------------------------------------- /packages/app-design-to-code/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./code-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-design-to-code/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/design-to-code", 3 | "version": "0.0.0", 4 | "private": false, 5 | "dependencies": { 6 | "re-resizable": "^6.9.1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/app-design-to-code/user-options.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkOption } from "./framework-option"; 2 | 3 | export type DesigntoCodeUserOptions = FrameworkOption; 4 | -------------------------------------------------------------------------------- /packages/app-i18n/index.ts: -------------------------------------------------------------------------------- 1 | export { GlobalizationScreen } from "./i18n-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-i18n/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/i18n", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/app-icons-loader/history.ts: -------------------------------------------------------------------------------- 1 | // save recently used items 2 | 3 | import type { Icon } from "./resources"; 4 | 5 | const _k_store_key = "icons-load-history"; 6 | 7 | export class IconsLoadHistory { 8 | private readonly data: Array = []; 9 | 10 | constructor(readonly max: number = 50) { 11 | const items = localStorage.getItem(_k_store_key); 12 | if (items) { 13 | this.data = JSON.parse(items); 14 | } 15 | } 16 | 17 | list(to: number = Infinity): Array { 18 | return Array.from(this.data).reverse().slice(0, to); 19 | } 20 | 21 | push(item: Icon) { 22 | const index = this.data.findIndex( 23 | (i) => 24 | i.package === item.package && 25 | i.name === item.name && 26 | i.variant === item.variant 27 | ); 28 | if (index >= 0) { 29 | this.data.splice(index, 1); 30 | } 31 | this.data.push(item); 32 | 33 | if (this.data.length > this.max) { 34 | this.data.shift(); 35 | } 36 | 37 | this.save(); 38 | } 39 | 40 | private save() { 41 | localStorage.setItem(_k_store_key, JSON.stringify(this.data)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/app-icons-loader/icons-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { IconsLoader } from "./icons-loader"; 3 | export function IconsScreen() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /packages/app-icons-loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./icons-screen"; 2 | export * from "./icons-loader"; 3 | -------------------------------------------------------------------------------- /packages/app-icons-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/icons-loader", 3 | "description": "icons loader related package", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": { 8 | "react-infinite-scroller": "^1.2.6" 9 | }, 10 | "devDependencies": { 11 | "@types/react-infinite-scroller": "^1.2.3" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/app-icons-loader/utils.ts: -------------------------------------------------------------------------------- 1 | export const debounce = (func: any, wait: number) => { 2 | let timeout: any; 3 | return function (this: any, ...args: any[]) { 4 | const context = this; 5 | clearTimeout(timeout); 6 | timeout = setTimeout(() => func.apply(context, args), wait); 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/app-live-session/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing on `"assistant live session"` 2 | 3 | ## setup `.env` 4 | 5 | Additional .env setup is required for this feature. **NOTE** that .env setup should be done at `/assistant/web/.env`, not under this directory. 6 | 7 | **setup pusher api** 8 | 9 | - `NEXT_PUSHER_APP_KEY` 10 | - `NEXT_PUSHER_APP_CLUSTER` 11 | -------------------------------------------------------------------------------- /packages/app-live-session/README.md: -------------------------------------------------------------------------------- 1 | # Assistant Live 2 | 3 | Assistant Live session support 4 | 5 | > This feature enables user to interact with figma, select nodes, the triggered events will be listened from the app (preview or vscode extension) so easily the code can be integrated to production repository. 6 | 7 | ## The room design 8 | 9 | 1. id based 10 | 2. one room per one owner (owner id is the id) - can't perform multiple sessions 11 | 3. wip. 12 | 13 | ## Setup & Contribution 14 | 15 | Read [contributing](./CONTRIBUTING.md) 16 | 17 | ## References 18 | 19 | - https://code.visualstudio.com/learn/collaboration/live-share 20 | -------------------------------------------------------------------------------- /packages/app-live-session/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./connection-and-user-selection-interactive-indicator"; 2 | -------------------------------------------------------------------------------- /packages/app-live-session/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pages"; 2 | -------------------------------------------------------------------------------- /packages/app-live-session/k/index.ts: -------------------------------------------------------------------------------- 1 | export const VSCODE_MARKET_URL = "https://grida.co/vscode"; 2 | -------------------------------------------------------------------------------- /packages/app-live-session/layouts/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./connected"; 2 | export * from "./signin-required"; 3 | export * from "./filekey-setup-required"; 4 | export * from "./onboarding"; 5 | export * from "./start"; 6 | -------------------------------------------------------------------------------- /packages/app-live-session/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/live", 3 | "description": "Live session triggered from assistant", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": { 8 | "pusher-js": "^7.0.3" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/app-live-session/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./main"; 2 | -------------------------------------------------------------------------------- /packages/app-live-session/storage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./need-to-show-onboarding"; 2 | -------------------------------------------------------------------------------- /packages/app-live-session/storage/need-to-show-onboarding.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// Onboarding data shall be stored on local storage. the onboarding proc is required once per install. (unlike filekey setup) 3 | /// 4 | 5 | const _key = "assistant-live-onboarding-proc-done"; 6 | 7 | export function needToShowOnboarding(): boolean { 8 | const shown = localStorage.getItem(_key) === "true"; 9 | return !shown; 10 | } 11 | 12 | export function setOnboardingShown(): void { 13 | window.localStorage.setItem(_key, "true"); 14 | } 15 | -------------------------------------------------------------------------------- /packages/app-meta-editor/batch-meta-editor/README.md: -------------------------------------------------------------------------------- 1 | # Batch meta editor 2 | > seeds or removed the meta data of targetted nodes 3 | 4 | ## Use case 5 | > the primaritive design of this feature was based on design library seeding. by seeding metadata to all components from the design library (mostly remote), assistant can tell if the instance is a managed component from specific well known design system. For example, Ant design or Material design. 6 | 7 | ## Limitations 8 | 9 | currently, we only support batch metadata edit operation by adding metadata on root document node. -------------------------------------------------------------------------------- /packages/app-meta-editor/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./meta-editor"; 2 | export * from "./batch-meta-editor"; 3 | export * from "./repository"; 4 | export * as mock from "./mock"; 5 | -------------------------------------------------------------------------------- /packages/app-meta-editor/meta-editor/README.md: -------------------------------------------------------------------------------- 1 | # Grida Assistant Meta Data Editor 2 | 3 | > this is a screen that enables developer's to edit meta data of selected layer, component, screen as a construct of provided data schema. 4 | 5 | ## Features 6 | 7 | - Add Schema - add a json schema structure of the meta data to be managed. 8 | - Update Schema - update existing meta data schema. 9 | - Add Seed - add seed data template (this can be used when using popular design systems such as [material design](https://material.io), [reflect ui](https://reflect-ui.com), [ant design](https://ant.design)) 10 | - Export Data - export data as a json file 11 | - Update Data - update the data linked to a layer / scene. 12 | - Versioning - versioning the schema, and the data. 13 | -------------------------------------------------------------------------------- /packages/app-meta-editor/mock/index.ts: -------------------------------------------------------------------------------- 1 | export class MetaDataMockDataProvider { 2 | static componentData() { 3 | return { 4 | docsUrl: "https://google.com" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /packages/app-meta-editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/meta-editor", 3 | "description": "icons loader related package", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": {} 8 | } -------------------------------------------------------------------------------- /packages/app-photo-loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./photo-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-photo-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/photo-loader", 3 | "description": "Photo loader for designers", 4 | "version": "0.0.0", 5 | "author": "Grida.co", 6 | "license": "MIT", 7 | "private": false, 8 | "dependencies": { 9 | "react-responsive-masonry": "^2.1.7", 10 | "react-select": "^5.7.0", 11 | "unsplash-js": "^7.0.15" 12 | }, 13 | "devDependencies": { 14 | "@types/react-responsive-masonry": "^2.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/app-photo-loader/photo-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { PhotoLoader } from "./photo-loader"; 3 | 4 | export function PhotoScreen() { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /packages/app-preferences/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./prefer-language"; 2 | export * from "./prefer-framework"; 3 | -------------------------------------------------------------------------------- /packages/app-preferences/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/preferences", 3 | "version": "0.0.0", 4 | "private": false, 5 | "author": "Grida.co" 6 | } -------------------------------------------------------------------------------- /packages/app-preferences/prefer-framework/index.ts: -------------------------------------------------------------------------------- 1 | import { Framework } from "@grida/builder-platform-types"; 2 | 3 | const key = "prefer-platform"; 4 | export class PreferFramework { 5 | readonly storage: Storage; 6 | 7 | constructor() { 8 | this.storage = window.localStorage; 9 | } 10 | set(platform: Framework) { 11 | this.storage.setItem(key, platform); 12 | } 13 | get(): Framework | undefined { 14 | return this.storage.getItem(key) as Framework; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/app-preferences/prefer-language/index.ts: -------------------------------------------------------------------------------- 1 | export class PreferLanguage {} 2 | -------------------------------------------------------------------------------- /packages/app-scene-export-json/README.md: -------------------------------------------------------------------------------- 1 | # UI Exporter 2 | 3 | - reflect json exporter - expors ui as a whole json tree 4 | 5 | ## Export mode 6 | 7 | - reflect vanilla 8 | - reflect standard 9 | - figma raw (only for figma platform) 10 | 11 | ## Export range 12 | 13 | - current page 14 | - whole docs 15 | - selecetd single node 16 | - selected nodes (this will download multiple files per selection) 17 | -------------------------------------------------------------------------------- /packages/app-scene-export-json/export-utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * this triggers the file download from the design tool you are interacting with 3 | */ 4 | export function downloadFile(content) { 5 | // @ts-ignore blob 6 | const blob = new Blob([content], { type: "text/plain" }); 7 | // @ts-ignore blob 8 | const url = window.URL.createObjectURL(blob); 9 | const a = document.createElement("a"); 10 | a.href = url; 11 | a.download = `export-node.json`; // TODO: make name more flexible 12 | a.click(); 13 | a.remove(); 14 | // @ts-ignore blob 15 | window.URL.revokeObjectURL(url); 16 | } 17 | -------------------------------------------------------------------------------- /packages/app-scene-export-json/exporter.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { FigmaExporter } from "./figma-exporter"; 3 | import { VanillaExporter } from "./vanilla-exporter"; 4 | 5 | export function ExporterScreen() { 6 | return ( 7 | <> 8 | 9 | 10 | ); 11 | // ; 12 | } 13 | -------------------------------------------------------------------------------- /packages/app-scene-export-json/index.tsx: -------------------------------------------------------------------------------- 1 | export { ExporterScreen } from "./exporter"; 2 | -------------------------------------------------------------------------------- /packages/app-scene-export-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/export-scene-as-json", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/app-scene-view/index.ts: -------------------------------------------------------------------------------- 1 | export { preview } from "./scene-preview"; 2 | export { registerScene } from "./register-scene"; 3 | -------------------------------------------------------------------------------- /packages/app-scene-view/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/scene-view", 3 | "description": "scene view related package", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": {} 8 | } -------------------------------------------------------------------------------- /packages/app-scene-view/scene-preview.ts: -------------------------------------------------------------------------------- 1 | import { Widget } from "@flutter-builder/flutter"; 2 | import { features } from "@base-sdk/base"; 3 | import { wrap_with_hosting__flutter } from "./_wrapping-for-hosting"; 4 | export async function preview(id: string, app: { raw: string }) { 5 | console.log("quicklook starting.."); 6 | 7 | // replace url as real one 8 | // dartSource.replace() 9 | 10 | const wrapped = await wrap_with_hosting__flutter(id, app); 11 | const previewurl = features.scene_preview.buildScenePreviewUrl({ 12 | id: wrapped.id, 13 | name: wrapped.name, 14 | framework: wrapped.framework, 15 | language: wrapped.language, 16 | url: wrapped.url, 17 | }); 18 | open(previewurl); 19 | console.log("launched!", previewurl); 20 | } 21 | -------------------------------------------------------------------------------- /packages/app-schema-editor/README.md: -------------------------------------------------------------------------------- 1 | # Visual Schema editor for defining custom schema for ui components 2 | -------------------------------------------------------------------------------- /packages/app-schema-editor/by-selection-state/_shared-components/index.ts: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | export const CodeStyleWrapper = styled.div` 4 | height: calc(100vh - 292px); 5 | background: #1e1e1e; 6 | overflow: auto; 7 | padding: 0 6px; 8 | `; 9 | -------------------------------------------------------------------------------- /packages/app-schema-editor/by-selection-state/index.ts: -------------------------------------------------------------------------------- 1 | export { default as BaseMaster } from "./selection-base-master-component"; 2 | export { default as ConfigurableLayer } from "./selection-configurable-layer"; 3 | export { default as InstanceComponent } from "./selection-instance-component"; 4 | export { default as MasterComponent } from "./selection-master-component"; 5 | export { default as VariantSet } from "./selection-variant-set"; 6 | export { default as VariantMaster } from "./selection-variant-master"; 7 | export { default as VariantInstance } from "./selection-variant-instance"; 8 | 9 | export { default as InvalidSelection } from "./selection-invalid"; 10 | export { default as NoSelection } from "./selection-none"; 11 | -------------------------------------------------------------------------------- /packages/app-schema-editor/by-selection-state/selection-base-master-component.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function () { 4 | return ( 5 | <> 6 |
base master component
7 | 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /packages/app-schema-editor/by-selection-state/selection-instance-component.coli.ts: -------------------------------------------------------------------------------- 1 | import { NameCases, ScopedVariableNamer } from "@coli.codes/naming"; 2 | 3 | import { InterfaceDeclaration } from "coli"; 4 | import { singleLayerPropertyMappingToPropertySignature } from "../interface-code-builder/single-layer-property-mapping-to-property-signature"; 5 | import { typeToColiType } from "../interface-code-builder/type-to-coli-type"; 6 | import { IProperties } from "../types"; 7 | import { ISingleLayerPropertyMapping } from "../types/single-layer-property-type"; 8 | 9 | export default function ({ 10 | mainInterfaceName, 11 | properties, 12 | propertyNamer, 13 | }: { 14 | mainInterfaceName: string; 15 | properties: IProperties; 16 | propertyNamer: ScopedVariableNamer; 17 | }) { 18 | const property_signatures = properties.map((d) => { 19 | return singleLayerPropertyMappingToPropertySignature({ 20 | singlePropertyMapping: d, 21 | propertyNamer, 22 | }); 23 | }); 24 | 25 | return new InterfaceDeclaration({ 26 | name: mainInterfaceName, 27 | members: [...property_signatures], 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /packages/app-schema-editor/by-selection-state/selection-variant-set.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as nodes from "@design-sdk/figma-node"; 3 | 4 | export default function (props: { 5 | node?: nodes.IReflectNodeReference; 6 | defaultComponent?: nodes.IReflectNodeReference; 7 | }) { 8 | // TODO 9 | return ( 10 | <> 11 |
variant set
12 |

select component inside variant set

; 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /packages/app-schema-editor/index.ts: -------------------------------------------------------------------------------- 1 | export { SchemaEditor } from "./schema-editor"; 2 | -------------------------------------------------------------------------------- /packages/app-schema-editor/interface-code-builder/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./props-builder"; 2 | export * from "./example-data-builder"; 3 | export * from "./jsx-view-example-builder"; 4 | -------------------------------------------------------------------------------- /packages/app-schema-editor/interface-code-builder/scoped-property-id-namer.ts: -------------------------------------------------------------------------------- 1 | import { ScopedVariableNamer } from "@coli.codes/naming"; 2 | import { ReservedKeywordPlatformPresets } from "coli"; 3 | 4 | const _default_key_val = "property-key"; 5 | export const reactNamer = (scope: string = _default_key_val) => 6 | new ScopedVariableNamer( 7 | _make_scope_name(scope), 8 | ReservedKeywordPlatformPresets.react 9 | ); 10 | 11 | export const tsNamer = (scope: string = _default_key_val) => 12 | new ScopedVariableNamer( 13 | _make_scope_name(scope), 14 | ReservedKeywordPlatformPresets.typescript 15 | ); 16 | 17 | const _make_scope_name = (scope: string) => 18 | scope === _default_key_val ? _default_key_val : `property-key-of-${scope}`; 19 | -------------------------------------------------------------------------------- /packages/app-schema-editor/interface-code-builder/single-layer-property-mapping-to-property-signature.ts: -------------------------------------------------------------------------------- 1 | import { NameCases } from "@coli.codes/naming"; 2 | import { FigmaNumber } from "@design-sdk/figma/dist/features/variant"; 3 | import { Identifier, PropertySignature } from "coli"; 4 | import { ISingleLayerPropertyMapping } from "../types/single-layer-property-type"; 5 | import { typeToColiType } from "./type-to-coli-type"; 6 | 7 | export function singleLayerPropertyMappingToPropertySignature({ 8 | singlePropertyMapping, 9 | propertyNamer, 10 | }: { 11 | singlePropertyMapping: ISingleLayerPropertyMapping; 12 | propertyNamer; 13 | }) { 14 | return new PropertySignature({ 15 | name: new Identifier( 16 | propertyNamer.nameit(singlePropertyMapping.schema.name, { 17 | case: NameCases.camel, 18 | }).name 19 | ), 20 | type: typeToColiType(FigmaNumber), // FIXME: use => n.schema.type 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /packages/app-schema-editor/interface-code-builder/type-to-coli-type.ts: -------------------------------------------------------------------------------- 1 | import { variant } from "@design-sdk/figma/dist/features"; 2 | import { 3 | FigmaBoolean, 4 | FigmaNumber, 5 | } from "@design-sdk/figma/dist/features/variant"; 6 | import { 7 | BooleanKeyword, 8 | LiteralType, 9 | NumberKeyword, 10 | StringLiteral, 11 | UnionType, 12 | } from "coli"; 13 | 14 | export function typeToColiType(t: variant.FigmaVariantPropertyCompatType) { 15 | if (t == FigmaNumber) { 16 | return new NumberKeyword(); 17 | } else if (t == FigmaBoolean) { 18 | return new BooleanKeyword(); 19 | } else if (t.type == "unique") { 20 | return new LiteralType(new StringLiteral(t.value)); 21 | } else if (t.type == "enum") { 22 | return new UnionType({ 23 | types: t.values.map((v) => { 24 | return new LiteralType(new StringLiteral(v)); 25 | }), 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/app-schema-editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/schema-editor", 3 | "description": "schema editor related package", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "private": false, 7 | "dependencies": { 8 | "@code-ui/completion-provider": "^0.0.4", 9 | "@code-ui/hover": "^0.0.2", 10 | "@code-ui/interface": "^0.0.5", 11 | "@code-ui/token": "^0.0.7", 12 | "@radix-ui/react-hover-card": "^0.1.0", 13 | "@tippyjs/react": "^4.2.5" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/app-schema-editor/types/index.ts: -------------------------------------------------------------------------------- 1 | import type { ISingleLayerPropertyMapping } from "./single-layer-property-type"; 2 | 3 | // region export 4 | export type IProperties = ISingleLayerPropertyMapping[]; 5 | export type { ISingleLayerPropertyMapping as ISingleLayerProperty } from "./single-layer-property-type"; 6 | -------------------------------------------------------------------------------- /packages/app-schema-editor/ux-messages/index.ts: -------------------------------------------------------------------------------- 1 | export const ERROR_MESSAGES = { 2 | nothing_is_selected: "Nothing is selected", 3 | you_must_select_instance_or_component_type_of_node: 4 | "You must select instance or component type of node.", 5 | }; 6 | -------------------------------------------------------------------------------- /packages/app-toolbox-home/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./toolbox-home"; 2 | -------------------------------------------------------------------------------- /packages/app-toolbox-home/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/toolbox", 3 | "version": "0.0.0" 4 | } -------------------------------------------------------------------------------- /packages/app-widget-maker-button/button-maker-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | export function ButtonMakerScreen() { 3 | function handleRandomizeClick(e: any) { 4 | parent.postMessage( 5 | { 6 | pluginMessage: { 7 | type: "reflect-ui-generation/button-base", 8 | data: undefined, 9 | }, 10 | }, 11 | "*" 12 | ); 13 | } 14 | 15 | return ( 16 |
17 |

Reflect button maker

18 | 19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/app-widget-maker-button/index.ts: -------------------------------------------------------------------------------- 1 | export { ButtonMakerScreen } from "./button-maker-screen"; 2 | -------------------------------------------------------------------------------- /packages/app-widget-maker-button/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@app/button-maker", 3 | "version": "0.0.0", 4 | "description": "Button maker", 5 | "private": false 6 | } -------------------------------------------------------------------------------- /packages/core-code-formatter/dart-format.ts: -------------------------------------------------------------------------------- 1 | import { formatCode } from "dart-style" 2 | 3 | // formatter contains some issue. https://github.com/Dart-Code/Dart-Code/issues/2822 4 | export function format(code: string): string { 5 | try { 6 | const formatted = formatCode(code); 7 | return formatted.code; 8 | } catch (e) { 9 | console.error(e); 10 | return code; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/core-code-formatter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@core/code-formatter", 3 | "description": "description", 4 | "authors": "Grida co", 5 | "version": "0.0.0", 6 | "dependencies": { 7 | "dart-style": "^1.3.2-dev" 8 | } 9 | } -------------------------------------------------------------------------------- /packages/core-constant/ek.constant.ts: -------------------------------------------------------------------------------- 1 | /// EK stands for "Event Key" 2 | /// the event keys constants 3 | 4 | export const EK_GENERATED_CODE_PLAIN = "EK_GENERATED_CODE_PLAIN"; 5 | export const EK_IMAGE_ASSET_REPOSITORY_MAP = "EK_IMAGE_ASSET_REPOSITORY_MAP"; 6 | export const EK_VANILLA_TRANSPORT = "EK_VANILLA_TRANSPORT"; 7 | export const EK_CURRENT_SELECTION_PREVIEW_SOURCE_CHANGED = 8 | "EK_CURRENT_SELECTION_PREVIEW_SOURCE_CHANGED"; 9 | // icon related 10 | export const EK_ICON_DRAG_AND_DROPPED = "assistant/design/icons/add/dropped"; 11 | export const EK_CREATE_ICON = "assistant/design/icons/add/create"; 12 | 13 | // image resource related 14 | export const EK_APPLY_IMAGE = "assistant/design/images/apply/create-or-update"; 15 | 16 | // text related 17 | export const EK_APPLY_TEXT_CHARACTERS = 18 | "assistant/design/text/characters/apply/create-or-update"; 19 | /** @deprecated migrate to custom app event */ 20 | export const EK_REPLACE_FONT = "EK_REPLACE_FONT"; 21 | 22 | // 23 | export const EK_SET_APP_MODE = "EK_SET_APP_MODE"; 24 | export const EK_COMPUTE_STARTED = "EK_COMPUTE_STARTED"; 25 | -------------------------------------------------------------------------------- /packages/core-constant/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * DO NOT CHANGE THIS KEY. CHANGING NS WILL CAUSE ALL SHARED DATA LOSE (technically not lose, but won't be longer able to access)) 3 | */ 4 | export const ASSISTANT_PLUGIN_NAMESPACE__NOCHANGE = "co.grida.assistant"; 5 | export * from "./ek.constant"; 6 | export * from "./ns.constant"; 7 | -------------------------------------------------------------------------------- /packages/core-constant/ns.constant.ts: -------------------------------------------------------------------------------- 1 | /// the namespace can only contain alphabetical characters, '.' and '_'. 2 | /// other characters such as '-', '/' are not allowed. this is because figma's setSharedPluginData does not allow this. 3 | 4 | export const NS_FILE_ROOT_METADATA = "xyz.bridged.assistant.file_root_metadata_v1" -------------------------------------------------------------------------------- /packages/core-constant/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@core/constant", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/icons-util/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 bridged.xyz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/icons-util/README.md: -------------------------------------------------------------------------------- 1 | ## Icons util 2 | 3 | - export icons set as font, or svg zip. 4 | - check for same icons vector 5 | - check for similar icons vector 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ## naming conventions 14 | > Follow reflect's icon [naming convention](https://www.notion.so/bridgedxyz/icon-naming-convention-7852e9590b064d509dc097f7580dc4c5) 15 | 16 | you can use [lint](https://github.com/bridgedxyz/lint) for icons linting 17 | 18 | ## Futrher Platform supports 19 | 20 | > make ready-for-developers code & font file 21 | 22 | flutter, js (react, vue or other web platforms) 23 | 24 | 25 | 26 | Copyright 2020. 27 | Part of [BRIDGED.XYZ](bridged.xyz) project -------------------------------------------------------------------------------- /packages/icons-util/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reflect.bridged.xyz/icons-util", 3 | "version": "0.1.0" 4 | } -------------------------------------------------------------------------------- /packages/platform-figma-checksum/__plugin/events.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | import { PluginSdkService } from "@plugin-sdk/service"; 3 | 4 | const EVKEY = "figma-checksum-custom-transport"; 5 | export interface SignatureSeedRequest { 6 | type: "seed-signature-request"; 7 | signature: string; 8 | /** 9 | * untrusted user provied filekey to be verified 10 | */ 11 | filekey: string; 12 | } 13 | 14 | export type _Checksum_Event = SignatureSeedRequest; 15 | 16 | export function fromApp(data: _Checksum_Event) { 17 | PluginSdk.appEvent(EVKEY, data); 18 | } 19 | 20 | export function onService(cb: (data: _Checksum_Event) => void) { 21 | PluginSdkService.onAppReqquest(EVKEY, cb); 22 | } 23 | -------------------------------------------------------------------------------- /packages/platform-figma-checksum/__plugin/index.ts: -------------------------------------------------------------------------------- 1 | import { onService, _Checksum_Event } from "./events"; 2 | import { FigmaRootNodeStoreVerification } from "@design-sdk/figma-checksum"; 3 | 4 | onService(main_cb); 5 | 6 | // main callback 7 | function main_cb(evt: _Checksum_Event) { 8 | switch (evt.type) { 9 | case "seed-signature-request": { 10 | const verifier = new FigmaRootNodeStoreVerification({ 11 | filekey: evt.filekey, 12 | signature: evt.signature, 13 | }); 14 | // prewarm shall be called on code thread of figma. 15 | verifier.prewarm(); 16 | 17 | // pending verfiication will be handled on ui thread with remote request. 18 | break; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/platform-figma-checksum/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./link-input"; 2 | -------------------------------------------------------------------------------- /packages/platform-figma-checksum/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./pages"; 2 | export * from "./store"; 3 | -------------------------------------------------------------------------------- /packages/platform-figma-checksum/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@platform-dedicated/figma-checksum", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/platform-figma-checksum/store.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | import { NS_FILE_ROOT_METADATA } from "@core/constant"; 3 | 4 | export const saveFilekey = async (filekey: string) => { 5 | return PluginSdk.updateMetadata({ 6 | type: "node-meta-update-request", 7 | id: "0:0", // 0:0 stands for root node 8 | key: "filekey", 9 | value: filekey, 10 | namespace: NS_FILE_ROOT_METADATA, 11 | }); 12 | }; 13 | 14 | export const loadFilekey = async (): Promise => { 15 | return await PluginSdk.fetchRootMetadata("filekey"); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/plugin-app/README.md: -------------------------------------------------------------------------------- 1 | # Plugin SDK React component 2 | 3 | ```tsx 4 | 5 | 6 | 7 | ``` 8 | -------------------------------------------------------------------------------- /packages/plugin-app/client-id/README.md: -------------------------------------------------------------------------------- 1 | # Anonymous unique client identifier using storage 2 | 3 | 1. rand gen client id 4 | 2. save client id 5 | 3. use id as unique id for both authenticate/unauthenticated user. 6 | -------------------------------------------------------------------------------- /packages/plugin-app/client-id/index.ts: -------------------------------------------------------------------------------- 1 | import { client_id_store } from "./store"; 2 | import { nanoid } from "nanoid/non-secure"; 3 | 4 | function makeid(): string { 5 | return `cid-${nanoid()}`; 6 | } 7 | 8 | function initially_register_this_client_to_storage() { 9 | const _id = makeid(); 10 | client_id_store.set(_id); 11 | client_id = _id; 12 | } 13 | 14 | /** 15 | * readonly for api usage. writing only accessible via `__set_client_id` 16 | * this is always ensured to be non-null and available by view access after plugin app is initialized. 17 | **/ 18 | export let client_id: string; 19 | 20 | export async function initialize() { 21 | const _existing_in_store = await client_id_store.get(); 22 | if (!_existing_in_store) { 23 | initially_register_this_client_to_storage(); 24 | } else { 25 | client_id = _existing_in_store; 26 | } 27 | return client_id; 28 | } 29 | -------------------------------------------------------------------------------- /packages/plugin-app/client-id/store.ts: -------------------------------------------------------------------------------- 1 | import { PluginSdk } from "@plugin-sdk/app"; 2 | const __client_id_store_key = "co.grida.assistant/user-client-id"; 3 | let __memory_cache_client_id: string = null; 4 | async function getClientId() { 5 | if (!__memory_cache_client_id) { 6 | __memory_cache_client_id = await PluginSdk.getItem( 7 | __client_id_store_key 8 | ); 9 | } 10 | return __memory_cache_client_id; 11 | } 12 | 13 | function setClientId(cid: string) { 14 | __memory_cache_client_id = cid; 15 | PluginSdk.setItem(__client_id_store_key, cid); 16 | } 17 | 18 | async function upsertClientId(cid: string): Promise { 19 | if (await getClientId()) { 20 | return __memory_cache_client_id; 21 | } 22 | setClientId(cid); 23 | return cid; 24 | } 25 | 26 | export const client_id_store = { 27 | get: getClientId, 28 | set: setClientId, 29 | upsert: upsertClientId, 30 | }; 31 | -------------------------------------------------------------------------------- /packages/plugin-app/index.ts: -------------------------------------------------------------------------------- 1 | export { PluginApp } from "./plugin-app"; 2 | export { client_id } from "./client-id"; 3 | export * from "./plugin-hooks"; 4 | -------------------------------------------------------------------------------- /packages/plugin-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugin-app", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/plugin-app/plugin-hooks/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/plugin-app/plugin-hooks/README.md -------------------------------------------------------------------------------- /packages/plugin-app/plugin-hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./use-selection"; 2 | export * from "./use-meta"; 3 | -------------------------------------------------------------------------------- /packages/plugin-app/plugin-hooks/use-meta.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { ASSISTANT_PLUGIN_NAMESPACE__NOCHANGE } from "@core/constant"; 3 | import { PluginSdk } from "@plugin-sdk/app"; 4 | 5 | export interface VisualComponentManifest { 6 | name: string; 7 | description: string; 8 | storybook: string; 9 | docsUrl: string; 10 | gitUrl: string; 11 | codeSnippet: string; 12 | } 13 | 14 | /** 15 | * @deprecated 16 | * @param id 17 | * @returns 18 | */ 19 | export function useMainComponentMeta( 20 | id?: string 21 | ): VisualComponentManifest | null { 22 | if (!id) { 23 | return; 24 | } 25 | 26 | const [data, setData] = useState(null); 27 | useEffect(() => { 28 | PluginSdk.fetchMainComponentMetadata({ 29 | type: "node-meta-fetch-request", 30 | id: id, 31 | namespace: ASSISTANT_PLUGIN_NAMESPACE__NOCHANGE, 32 | key: "component-meta-data", 33 | }).then((d) => { 34 | setData(d); 35 | }); 36 | }); 37 | 38 | return data; 39 | } 40 | -------------------------------------------------------------------------------- /packages/plugin-app/states/canvas.ts: -------------------------------------------------------------------------------- 1 | import type { ReflectSceneNode } from "@design-sdk/core/nodes"; 2 | import { atom, GetRecoilValue, selector } from "recoil"; 3 | 4 | const ATOM_KEY_CURRENT_NODE_SELECTION_PRIMARY = 5 | "state.selection.node.primary.id"; 6 | const SELECT_KEY_CURRENT_NODE_SELECTION_PRIMARY = 7 | "state.selection.node.primary"; 8 | 9 | // current primary selected node's id 10 | export const currentlySelectedPrimaryNodeId = atom({ 11 | key: ATOM_KEY_CURRENT_NODE_SELECTION_PRIMARY, 12 | default: "", 13 | }); 14 | 15 | // current primary selected node 16 | export const currentlySelectedPrimaryNode = selector({ 17 | get: ({ get }) => { 18 | const id = get(currentlySelectedPrimaryNodeId); 19 | // TODO fetch node data via id 20 | throw "not implemeted"; 21 | }, 22 | key: SELECT_KEY_CURRENT_NODE_SELECTION_PRIMARY, 23 | }); 24 | -------------------------------------------------------------------------------- /packages/plugin-app/utils/canvas.ts: -------------------------------------------------------------------------------- 1 | import type { ReflectSceneNode } from "@design-sdk/figma-node"; 2 | 3 | export function getPrimarySelectedNode(selection: readonly ReflectSceneNode[]) { 4 | // if (){ 5 | // } 6 | } 7 | 8 | export enum SelectionAnalysis { 9 | empty = "empty", 10 | single = "single", 11 | multi = "multi", 12 | } 13 | 14 | export function analyzeSelection(selection: readonly any[]): SelectionAnalysis { 15 | if (selection.length == 0) { 16 | return SelectionAnalysis.empty; 17 | } else if (selection.length == 1) { 18 | return SelectionAnalysis.single; 19 | } else { 20 | return SelectionAnalysis.multi; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/plugin-app/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./canvas"; 2 | -------------------------------------------------------------------------------- /packages/plugin-sdk-app/_shared-storage-cache.ts: -------------------------------------------------------------------------------- 1 | /** Memory cache for saving data in memory before actual IO completes. */ 2 | export class _SharedStorageCache { 3 | constructor(readonly id: string) {} 4 | 5 | private __cache: Map = new Map(); 6 | 7 | hasCache(key: string): boolean { 8 | return this.__cache.has(key); 9 | } 10 | 11 | setCache(key: string, value: T) { 12 | this.__cache.set(key, value); 13 | } 14 | 15 | getCache(key: string): T { 16 | return this.__cache.get(key) as T; 17 | } 18 | 19 | /** clears all cahce allocated */ 20 | clearCache() { 21 | this.__cache = new Map(); 22 | } 23 | 24 | removeCache(key: string) { 25 | this.__cache.delete(key); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/plugin-sdk-app/index.ts: -------------------------------------------------------------------------------- 1 | export { PluginSdk } from "./plugin-sdk"; 2 | export { NodeApi } from "./node-api"; 3 | -------------------------------------------------------------------------------- /packages/plugin-sdk-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@plugin-sdk/app", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/plugin-sdk-core/_id/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * custom rand id generator for managin local mem request id 3 | * 1. not using nanoid - which is bridged standard, since nanoid won't work on some platform (e.g. figma) 4 | * 2. it doesn't have to be a sequre or complex id, since it's used locally 5 | * @param length 6 | * @returns 7 | */ 8 | export function reqid(length = 5) { 9 | const result = []; 10 | const characters = 11 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 12 | const charactersLength = characters.length; 13 | for (let i = 0; i < length; i++) { 14 | result.push( 15 | characters.charAt(Math.floor(Math.random() * charactersLength)) 16 | ); 17 | } 18 | return result.join(""); 19 | } 20 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./_id"; 2 | export * from "./interfaces"; 3 | export * from "./events"; 4 | export * from "./target-platform"; 5 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/dragdrop/dragdrop.requests.ts: -------------------------------------------------------------------------------- 1 | export interface DragAndDropOnCanvasRequest { 2 | dropPosition: { 3 | clientX: number; 4 | clientY: number; 5 | }; 6 | windowSize: { 7 | width: number; 8 | height: number; 9 | }; 10 | offset: { 11 | x: number; 12 | y: number; 13 | }; 14 | itemSize: { 15 | width: number; 16 | height: number; 17 | }; 18 | eventKey: string; 19 | customData: T; 20 | } 21 | 22 | export type DragAndDropHandlerCallback = ( 23 | customData: any, 24 | position: { x: number; y: number } 25 | ) => Promise; 26 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/dragdrop/dragdrop.responses.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/plugin-sdk-core/interfaces/dragdrop/dragdrop.responses.ts -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/dragdrop/dragdrop.types.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/plugin-sdk-core/interfaces/dragdrop/dragdrop.types.ts -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/dragdrop/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./dragdrop.requests"; 2 | // export * from "./dragdrop.responses"; 3 | // export * from "./dragdrop.types"; 4 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/export-image/export-image.requests.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ImageExportOptions, 3 | QuickImageExportPreset, 4 | _ImageExportOption_to_FigmaCompat, 5 | } from "./export-image.types"; 6 | 7 | export interface ImageExportRequest { 8 | id: string; 9 | opt: ImageExportOptions | QuickImageExportPreset; 10 | } 11 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/export-image/export-image.responses.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ImageExportOptions, 3 | QuickImageExportPreset, 4 | } from "./export-image.types"; 5 | 6 | export interface ImageExportResponse { 7 | id: string; 8 | data: Uint8Array; 9 | opt: ImageExportOptions | QuickImageExportPreset; 10 | } 11 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/export-image/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./export-image.requests"; 2 | export * from "./export-image.responses"; 3 | export * from "./export-image.types"; 4 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/focus/focus.requests.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * holder interface for focusing to target node with zoom 3 | */ 4 | export interface FocusRequest { 5 | /** target node/layer id */ 6 | target: string; 7 | /** zoom */ 8 | zoom?: number; 9 | } 10 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/focus/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./focus.requests"; 2 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./dragdrop"; 2 | export * from "./export-image"; 3 | export * from "./meta"; 4 | export * from "./notify"; 5 | export * from "./remote-api"; 6 | export * from "./storage"; 7 | export * from "./focus"; 8 | export * from "./uicontrol"; 9 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/meta/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./meta.requests"; 2 | // export * from "./meta.responses"; // empty 3 | export * from "./meta.types"; 4 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/meta/meta.requests.ts: -------------------------------------------------------------------------------- 1 | import { BatchMetaOperationTargetType } from "./meta.types"; 2 | 3 | export type MetaRequest = 4 | | BatchMetaUpdateRequest 5 | | BatchMetaFetchRequest 6 | | NodeMetaFetchRequest 7 | | NodeMetaUpdateRequest; 8 | 9 | export interface BatchMetaUpdateRequest { 10 | type: "batch-meta-update-request"; 11 | targetType: BatchMetaOperationTargetType; 12 | custom: T; 13 | key: string; 14 | value: string; 15 | } 16 | 17 | export interface BatchMetaFetchRequest { 18 | type: "batch-meta-fetch-request"; 19 | key: string; 20 | } 21 | 22 | export interface NodeMetaFetchRequest { 23 | type: "node-meta-fetch-request"; 24 | /** 25 | * the id of node 26 | */ 27 | id: string; 28 | namespace: string; 29 | key: string; 30 | } 31 | 32 | export interface NodeMetaUpdateRequest { 33 | type: "node-meta-update-request"; 34 | /** 35 | * the id of node 36 | */ 37 | id: string; 38 | namespace: string; 39 | key: string; 40 | value: T; 41 | } 42 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/meta/meta.responses.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/plugin-sdk-core/interfaces/meta/meta.responses.ts -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/meta/meta.types.ts: -------------------------------------------------------------------------------- 1 | export enum BatchMetaOperationTargetType { 2 | root = "document.root", 3 | all = "nodes.all", 4 | components = "nodes.components", 5 | // not supported yet. 6 | // uncomment this and implement each cases when first, batch component meta editing PR is merged. 7 | // origin author - @softmarshmallow 8 | // --------- 9 | // custom = 'custom', 10 | // instances = 'nodes.instances', 11 | // variants = 'nodes.variants' 12 | // --------- 13 | } 14 | export const SupportedBatchMetaOperationTargetTypes = [ 15 | BatchMetaOperationTargetType.root, 16 | ]; 17 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/notify/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./notify.requests"; 2 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/notify/notify.requests.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * holder interface for displaying notice on screen. (figma native api.) 3 | */ 4 | export interface NotifyRequest { 5 | // message to display 6 | message: string; 7 | // in seconds 8 | duration: number; 9 | } 10 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/remote-api/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./remote-api.requests"; 2 | // export * from "./remote-api.responses"; 3 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/remote-api/remote-api.requests.ts: -------------------------------------------------------------------------------- 1 | export interface NetworkRequest { 2 | requestId: string; 3 | method: "post" | "get" | "put" | "patch" | "head"; 4 | url: string; 5 | data?: object; 6 | headers?: object; 7 | } 8 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/remote-api/remote-api.responses.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/plugin-sdk-core/interfaces/remote-api/remote-api.responses.ts -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/storage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./storage.request"; 2 | export * from "./storage.response"; 3 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/storage/storage.request.ts: -------------------------------------------------------------------------------- 1 | export type StorageRequest = StorageSetItemRequest | StorageGetItemRequest; 2 | export interface StorageSetItemRequest { 3 | type: "set-item"; 4 | key: string; 5 | /** value must be json serializable. (without circular reference.) */ 6 | value: T; 7 | } 8 | 9 | export interface StorageGetItemRequest { 10 | type: "get-item"; 11 | key: string; 12 | } 13 | 14 | export interface StorageRemoveItemRequest { 15 | type: "remove-item"; 16 | key: string; 17 | } 18 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/storage/storage.response.ts: -------------------------------------------------------------------------------- 1 | export interface StorageGetItemResponse { 2 | value: T; 3 | } 4 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/uicontrol/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./uicontrol.request"; 2 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/interfaces/uicontrol/uicontrol.request.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PLUGIN_SDK_EK_UI_RESIZE, 3 | PLUGIN_SDK_EK_UI_CLOSE, 4 | PLUGIN_SDK_EK_UI_SHOW, 5 | PLUGIN_SDK_EK_UI_HIDE, 6 | } from "../../events"; 7 | 8 | export type UIControlRequest = 9 | | UIControlResizeRequest 10 | | UIControlCloseRequest 11 | | UIControlHideRequest 12 | | UIControlShowRequest; 13 | 14 | export interface UIControlResizeRequest { 15 | type: typeof PLUGIN_SDK_EK_UI_RESIZE; 16 | size: { width: number; height: number }; 17 | } 18 | 19 | export interface UIControlCloseRequest { 20 | type: typeof PLUGIN_SDK_EK_UI_CLOSE; 21 | } 22 | 23 | export interface UIControlHideRequest { 24 | type: typeof PLUGIN_SDK_EK_UI_HIDE; 25 | } 26 | 27 | export interface UIControlShowRequest { 28 | type: typeof PLUGIN_SDK_EK_UI_SHOW; 29 | } 30 | -------------------------------------------------------------------------------- /packages/plugin-sdk-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@plugin-sdk/core", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/plugin-sdk-core/target-platform/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Target platform this ui runs on. this gloval variable will be set on initial entry on each platform's main ui import 3 | */ 4 | let TARGET_PLATFORM: TargetPlatform; 5 | 6 | export const target_platform = { 7 | get: (): TargetPlatform => TARGET_PLATFORM, 8 | set: (value: TargetPlatform) => { 9 | TARGET_PLATFORM = value; 10 | }, 11 | }; 12 | 13 | export enum TargetPlatform { 14 | bridged = "xyz.bridged.bridged", 15 | figma = "com.figma.Desktop", 16 | sketch = "com.bohemiancoding.sketch3", 17 | xd = "xd", 18 | zeplin = "zeplin", 19 | webdev = "xyz.bridged.assistant-web-dev", 20 | } 21 | -------------------------------------------------------------------------------- /packages/plugin-sdk-draggable/README.md: -------------------------------------------------------------------------------- 1 | ## Drag and Drop implementation on figma platform 2 | 3 | > The original code is from https://github.com/jackiecorn/figma-plugin-drag-and-drop 4 | 5 | This feature is deprecated. 6 | 7 | ### Reason 8 | 9 | - Drag and Drop does not work in iframe within iframe 10 | 11 | ### Solution 12 | 13 | - Disable iframe on pages use drag and drop 14 | - Overlap dragable component on original iframe 15 | - Do not use iframe within iframe 16 | - Wait for the Figma api update to receive the position of the plugin window 17 | 18 | ### Issue 19 | 20 | https://github.com/gridaco/assistant/issues/136 21 | -------------------------------------------------------------------------------- /packages/plugin-sdk-draggable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@plugin-sdk/draggable", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/plugin-sdk-service/README.md: -------------------------------------------------------------------------------- 1 | # Plugin provider to handle general api request 2 | 3 | ## The problem 4 | 5 | - figma ui.ts cannot access figma's api. 6 | - figma code.ts cannot access networ request. 7 | 8 | The middleware ping-pong operator. 9 | 10 | ## Whats in the box. 11 | 12 | - PluginApp React Component for ui.ts usage. 13 | - PluginServer Middleware for code.ts usage. 14 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@plugin-sdk/service", 3 | "version": "0.0.0", 4 | "private": false 5 | } -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/README.md: -------------------------------------------------------------------------------- 1 | # Universal storage 2 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/figma.storage.ts: -------------------------------------------------------------------------------- 1 | import { IStorage } from "./istorage"; 2 | import { encode, decode } from "./payload-handle"; 3 | import { plugin } from "@design-sdk/figma"; 4 | /** 5 | * storage on figma platform using `figma.clientStorage` 6 | */ 7 | export class FigmaStorage implements IStorage { 8 | async setItem(key: string, value: T) { 9 | const _payload = encode(value); 10 | await plugin.clientStorage.setAsync(key, _payload); 11 | } 12 | 13 | async getItem(key: string): Promise { 14 | const _payload = await plugin.clientStorage.getAsync(key); 15 | return decode(_payload); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./web.storage"; 2 | export * from "./figma.storage"; 3 | export type { IStorage } from "./istorage"; 4 | export { LayerMetadataStorage } from "./metadata"; 5 | // do not export universal storage until it is fullly implemented 6 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/istorage.ts: -------------------------------------------------------------------------------- 1 | export interface IStorage { 2 | getItem(key: string): Promise; 3 | setItem(key: string, value: T); 4 | } 5 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/metadata/README.md: -------------------------------------------------------------------------------- 1 | # Layer storage - a.k.a Metadata storage 2 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/payload-handle.ts: -------------------------------------------------------------------------------- 1 | export function encode(payload: T): string { 2 | return JSON.stringify(payload); 3 | } 4 | 5 | export function decode(payload: string): T { 6 | try { 7 | if (payload !== null && payload !== undefined) { 8 | return JSON.parse(payload) as T; 9 | } 10 | return null; 11 | } catch (_) { 12 | return null; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/universal.storage.ts: -------------------------------------------------------------------------------- 1 | import { IStorage } from "./istorage"; 2 | 3 | /** @deprecated not implemented. */ 4 | export class UniversalStorage implements IStorage { 5 | // storage cache 6 | setItem(key: string, value: string) { 7 | // 8 | } 9 | getItem(key: string): Promise { 10 | return; 11 | // 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/plugin-sdk-service/storage/web.storage.ts: -------------------------------------------------------------------------------- 1 | import { IStorage } from "./istorage"; 2 | import { encode, decode } from "./payload-handle"; 3 | 4 | /** 5 | * web storage using general localstorage 6 | */ 7 | export class WebStorage implements IStorage { 8 | getItem(key: string): Promise { 9 | return decode(window.localStorage.getItem(key)); 10 | } 11 | 12 | setItem(key: string, value: T) { 13 | window.localStorage.setItem(key, encode(value)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/toolbox-font-replacer/font-replacer-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Button } from "@material-ui/core"; 3 | import { EK_REPLACE_FONT } from "@core/constant/ek.constant"; 4 | 5 | export function FontReplacerScreen() { 6 | function onReplaceFontClick() { 7 | parent.postMessage( 8 | { 9 | pluginMessage: { 10 | type: EK_REPLACE_FONT, 11 | data: { 12 | // todo add more options for user to chose font maps to be replaced 13 | }, 14 | }, 15 | }, 16 | "*" 17 | ); 18 | } 19 | 20 | return ( 21 |
22 | WARNING! this is a hightly distructive operation. 23 |

24 | converts all text in selected frame as Roboto Regular. this can be used 25 | when no font on original design is installed on your device. 26 |

27 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /packages/toolbox-font-replacer/index.ts: -------------------------------------------------------------------------------- 1 | export { FontReplacerScreen } from "./font-replacer-screen"; 2 | -------------------------------------------------------------------------------- /packages/toolbox-font-replacer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@toolbox/font-replacer", 3 | "version": "0.0.0", 4 | "private": false, 5 | "description": "Mini Font replacer tool" 6 | } -------------------------------------------------------------------------------- /packages/toolbox-realtime-selection-sync/README.md: -------------------------------------------------------------------------------- 1 | # Realtime selection socket transpport 2 | 3 | This will be moved into design-sdk after properly implemented. 4 | 5 | This sends data via socket for design-to-code development 6 | -------------------------------------------------------------------------------- /packages/ui-code-box/README.md: -------------------------------------------------------------------------------- 1 | ## Codebox 2 | 3 | ## Monaco editor issues. 4 | 5 | 1. loading speed 6 | 2. height. - https://github.com/microsoft/monaco-editor/issues/794#issuecomment-688959283 7 | -------------------------------------------------------------------------------- /packages/ui-code-box/editors/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./monaco-editor"; 2 | export * from "./prism-view"; 3 | -------------------------------------------------------------------------------- /packages/ui-code-box/editors/monaco-utils/README.md: -------------------------------------------------------------------------------- 1 | This directory is a clone of design-to-code's `monaco-utils` 2 | -------------------------------------------------------------------------------- /packages/ui-code-box/editors/monaco-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * as register from "./register"; 2 | -------------------------------------------------------------------------------- /packages/ui-code-box/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./codebox"; 2 | export * from "./codebox-edit-dialog"; 3 | -------------------------------------------------------------------------------- /packages/ui-code-box/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ui/codebox", 3 | "version": "0.0.0", 4 | "private": false, 5 | "dependencies": { 6 | "@monaco-editor/react": "^4.4.1", 7 | "monaco-editor": "^0.33.0" 8 | } 9 | } -------------------------------------------------------------------------------- /packages/ui-core/button/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/ui-core/button/index.ts -------------------------------------------------------------------------------- /packages/ui-core/column/index.ts: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | export const Column = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | `; 7 | -------------------------------------------------------------------------------- /packages/ui-core/divider/divider.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React from "react"; 3 | export function Divider({ 4 | theme = "light", 5 | color = "#bbb", 6 | }: { 7 | theme?: "dark" | "light"; 8 | color?: string; 9 | }) { 10 | return ; 11 | } 12 | 13 | const DividerStyled = styled.div` 14 | border-top: 1px solid #bbb; 15 | `; 16 | -------------------------------------------------------------------------------- /packages/ui-core/divider/index.ts: -------------------------------------------------------------------------------- 1 | export { Divider } from "./divider"; 2 | -------------------------------------------------------------------------------- /packages/ui-core/index.ts: -------------------------------------------------------------------------------- 1 | export { Row } from "./row"; 2 | export { Column } from "./column"; 3 | export { Divider } from "./divider"; 4 | -------------------------------------------------------------------------------- /packages/ui-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ui/core", 3 | "description": "Assistant ui cores", 4 | "authors": "Grida co", 5 | "version": "0.0.0", 6 | "dependencies": { 7 | "@material-ui/core": "^4.11.0", 8 | "@material-ui/icons": "^4.11.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/ui-core/row/index.ts: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | export const Row = styled.div` 4 | display: flex; 5 | flex-direction: row; 6 | `; 7 | -------------------------------------------------------------------------------- /packages/ui-core/search/index.ts: -------------------------------------------------------------------------------- 1 | export { SearchInput } from "./search"; 2 | -------------------------------------------------------------------------------- /packages/ui-flow-steps/components/animated-check-icon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | 4 | import { motion } from "framer-motion"; 5 | import CheckIcon from "@assistant/icons/check"; 6 | 7 | const variants = { 8 | "make-active": { 9 | opacity: 1, 10 | scale: 1.05, 11 | fill: "#2562FF", 12 | transition: { ease: "easeOut", duration: 0.2 }, 13 | }, 14 | }; 15 | 16 | export function AnimatedCheckIcon() { 17 | return ( 18 | 25 | 26 | 27 | ); 28 | } 29 | 30 | const StyledCheckIcon = styled(motion.div)``; 31 | -------------------------------------------------------------------------------- /packages/ui-flow-steps/components/animated-progress-bar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | 4 | import { AnimatePresence, motion } from "framer-motion"; 5 | 6 | interface IProgressBar { 7 | initial?: number; 8 | height?: React.CSSProperties["height"]; 9 | onAnimationComplete?: () => void; 10 | } 11 | 12 | export function AnimatedProgressBar({ 13 | initial = 10, 14 | height = 4, 15 | onAnimationComplete, 16 | }: IProgressBar) { 17 | return ( 18 | 19 | {/* @ts-ignore */} 20 | 21 | 33 | 34 | 35 | ); 36 | } 37 | 38 | const Base = styled.div` 39 | background: #f5f5f5; 40 | `; 41 | 42 | const Bar = styled(motion.div)` 43 | background: #2562ff; 44 | `; 45 | -------------------------------------------------------------------------------- /packages/ui-flow-steps/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./animated-check-icon"; 2 | export * from "./animated-progress-bar"; 3 | -------------------------------------------------------------------------------- /packages/ui-flow-steps/index.ts: -------------------------------------------------------------------------------- 1 | export { UploadSteps } from "./scaffold"; 2 | -------------------------------------------------------------------------------- /packages/ui-flow-steps/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ui/flow-steps", 3 | "description": "Assistant ui upload (flow) steps", 4 | "authors": "grida.co", 5 | "version": "0.0.0", 6 | "dependencies": {} 7 | } -------------------------------------------------------------------------------- /packages/ui-flow-steps/scaffold/index.ts: -------------------------------------------------------------------------------- 1 | export { UploadSteps } from "./upload-steps"; 2 | -------------------------------------------------------------------------------- /packages/ui-icons/arrow-left.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function ArrowLeftIcon() { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui-icons/back-arrow.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function BackArrowIcon() { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui-icons/caret-down.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function CaretDownIcon(props: any): JSX.Element { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui-icons/caret-left.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function CaretLeftIcon() { 4 | return ( 5 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /packages/ui-icons/caret-right.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function CaretRightIcon() { 4 | return ( 5 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /packages/ui-icons/caret-up.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function CaretUpIcon() { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui-icons/check.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function CheckIcon() { 4 | return ( 5 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /packages/ui-icons/expand-down.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function ExpandDownIcon() { 4 | return ( 5 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /packages/ui-icons/expand-right.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | export default function ExpandRightIcon() { 3 | return ( 4 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /packages/ui-icons/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./back-arrow"; 2 | export * from "./caret-down"; 3 | export * from "./caret-up"; 4 | export * from "./caret-left"; 5 | export * from "./caret-right"; 6 | -------------------------------------------------------------------------------- /packages/ui-icons/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assistant/icons", 3 | "description": "Icons used for assistant app (React)", 4 | "authors": "Grida", 5 | "version": "0.0.0", 6 | "dependencies": { 7 | "@radix-ui/react-icons": "^1.2.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/ui-icons/pagination-left.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function PaginationLeftIcon() { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui-icons/pagination-right.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | export default function PaginationRightIcon() { 3 | return ( 4 | 11 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/ui-icons/warning.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | export default function Warning() { 3 | return ( 4 | 11 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/ui-lint-icons/error-missing-color-style.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function LintErrorMissingColorStyleIcon() { 4 | return ( 5 | 12 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/ui-lint-icons/error-missing-text-style.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function MissingTextStyleErrorIcon() { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui-lint-icons/error-naming.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function NamingLintErrorIcon() { 4 | return ( 5 | 12 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/ui-lint-icons/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./error-missing-color-style"; 2 | export * from "./error-missing-text-style"; 3 | export * from "./error-naming"; 4 | -------------------------------------------------------------------------------- /packages/ui-lint-icons/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assistant/lint-icons", 3 | "description": "Icons used for lint", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "dependencies": {} 7 | } -------------------------------------------------------------------------------- /packages/ui-previewer/.design/design-concept-archive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/packages/ui-previewer/.design/design-concept-archive.png -------------------------------------------------------------------------------- /packages/ui-previewer/README.md: -------------------------------------------------------------------------------- 1 | # `@ui/previewer` 2 | 3 | ![](.design/design-concept-archive.png) 4 | -------------------------------------------------------------------------------- /packages/ui-previewer/cache/index.ts: -------------------------------------------------------------------------------- 1 | import { ImageExportOptions, QuickImageExportPreset } from "@plugin-sdk/core"; 2 | 3 | type SerializableImageExportOption = 4 | | ImageExportOptions 5 | | QuickImageExportPreset; 6 | 7 | export class PreviewSessionCache { 8 | private readonly key; 9 | constructor( 10 | readonly node: string, 11 | readonly setting: SerializableImageExportOption 12 | ) { 13 | this.key = `${node}-${ 14 | typeof setting === "string" ? setting : JSON.stringify(setting) 15 | }`; 16 | } 17 | 18 | setCache(data: Uint8Array) { 19 | const payload = JSON.stringify(Array.from(data)); 20 | payload && window.localStorage.setItem(this.key, payload); 21 | } 22 | 23 | getCache(): Uint8Array | null { 24 | const payload = window.localStorage.getItem(this.key); 25 | return payload && new Uint8Array(JSON.parse(payload)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/ui-previewer/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./preview-empty"; 2 | -------------------------------------------------------------------------------- /packages/ui-previewer/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./preview"; 2 | export * as utils from "./utils"; 3 | -------------------------------------------------------------------------------- /packages/ui-previewer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ui/previewer", 3 | "version": "0.0.0", 4 | "private": false, 5 | "dependencies": { 6 | "@code-editor/vanilla-preview": "^0.0.2", 7 | "re-resizable": "^6.9.1", 8 | "react-use-measure": "^2.1.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/ui-previewer/preview-static-snapshot/README.md: -------------------------------------------------------------------------------- 1 | # Preview - Static image of design 2 | -------------------------------------------------------------------------------- /packages/ui-previewer/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./inject-asset-source"; 2 | -------------------------------------------------------------------------------- /packages/ui-skeleton/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./skeleton"; 2 | -------------------------------------------------------------------------------- /packages/ui-skeleton/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ui/skeleton", 3 | "description": "", 4 | "authors": "Grida.co", 5 | "version": "0.0.0", 6 | "dependencies": { 7 | "@emotion/react": "^11.4.1", 8 | "@emotion/styled": "^11.3.0", 9 | "@material-ui/lab": "^4.0.0-alpha.60" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/ui-theme/dark.ts: -------------------------------------------------------------------------------- 1 | import * as lightTheme from "./light"; 2 | 3 | export const colors = { 4 | ...lightTheme.colors, 5 | text: "rgb(248,248,250)", 6 | textMuted: "rgb(180,180,180)", 7 | textDisabled: "rgb(100,100,100)", 8 | inputBackground: "rgb(50,50,52)", 9 | divider: "rgba(255,255,255,0.1)", 10 | canvas: { 11 | ...lightTheme.colors.canvas, 12 | background: "rgb(19,20,21)", 13 | }, 14 | }; 15 | 16 | export const textStyles = lightTheme.textStyles; 17 | export const fonts = lightTheme.fonts; 18 | export const sizes = lightTheme.sizes; 19 | 20 | export const dark = { 21 | colors: colors, 22 | fonts: fonts, 23 | textStyles: textStyles, 24 | sizes: sizes, 25 | }; 26 | -------------------------------------------------------------------------------- /packages/ui-theme/index.ts: -------------------------------------------------------------------------------- 1 | import { light } from "./light"; 2 | import { dark } from "./dark"; 3 | import styled, { CreateStyled } from "@emotion/styled"; 4 | export * from "./theme-provider"; 5 | 6 | export const theme = { 7 | dark: dark, 8 | light: light, 9 | }; 10 | 11 | type _Theme = typeof light; 12 | export type Theme = _Theme; 13 | 14 | declare module "@emotion/react" { 15 | export interface Theme extends _Theme {} 16 | } 17 | 18 | // //@ts-ignore - below line sometimes throw "Type error: Type 'CreateStyled' is not generic." even if it is generic typed 19 | // export default styled as CreateStyled<_Theme>; 20 | -------------------------------------------------------------------------------- /packages/ui-theme/media-query.ts: -------------------------------------------------------------------------------- 1 | export const size = { 2 | medium: "800px", 3 | large: "1280px", 4 | xlarge: "1550px", 5 | xxlarge: "1680px", 6 | }; 7 | 8 | export const mediaQuery = { 9 | small: `@media (max-width: ${size.medium})`, 10 | medium: `@media (max-width: ${size.large}) and (min-width: ${size.medium})`, 11 | large: `@media (max-width: ${size.xlarge}) and (min-width: ${size.large})`, 12 | xlarge: `@media (min-width: ${size.xlarge})`, 13 | }; 14 | -------------------------------------------------------------------------------- /packages/ui-theme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ui/theme", 3 | "version": "0.0.0", 4 | "private": false, 5 | "author": "Grida.co", 6 | "license": "MIT" 7 | } -------------------------------------------------------------------------------- /services/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | 3 | # Serverless directories 4 | .serverless/ 5 | 6 | # DynamoDB Local files 7 | .dynamodb/ 8 | 9 | # build artifacts 10 | .build 11 | .webpack 12 | -------------------------------------------------------------------------------- /services/README.md: -------------------------------------------------------------------------------- 1 | # Assistant Serverless functions 2 | -------------------------------------------------------------------------------- /services/assistant-early-access/READMD.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/services/assistant-early-access/READMD.md -------------------------------------------------------------------------------- /services/assistant-early-access/scripts/dev-activation-key-gen.ts: -------------------------------------------------------------------------------- 1 | import { randomBytes } from "crypto"; 2 | 3 | for (let i = 0; i < 100; i++) { 4 | // Generate a random buffer 5 | const randomBuffer = randomBytes(16); 6 | 7 | // Convert the buffer to a string and pad it with leading zeros 8 | const key = randomBuffer.toString("hex"); 9 | 10 | // Construct the activation key with the prefix and padded number 11 | const activationKey = `GAEBAK-${key}`; 12 | // Output the activation key 13 | console.log(activationKey); 14 | } 15 | -------------------------------------------------------------------------------- /services/assistant-early-access/scripts/dev-totp-key-gen.ts: -------------------------------------------------------------------------------- 1 | import * as base32 from "thirty-two"; 2 | import { randomBytes } from "crypto"; 3 | 4 | for (let i = 0; i < 100; i++) { 5 | // Generate a random secret key 6 | const secretKey = randomBytes(20); 7 | 8 | // Encode the secret key in base32 format 9 | const encodedKey = base32.encode(secretKey).toString(); 10 | const qr = 11 | "otpauth://totp/Assistant%20Early%20Acess?secret=" + 12 | encodedKey + 13 | "&issuer=Grida"; 14 | 15 | // Output the secret key and QR code URL 16 | console.log(encodedKey, qr); 17 | } 18 | -------------------------------------------------------------------------------- /services/assistant-early-access/scripts/dev-totp-qrcode.ts: -------------------------------------------------------------------------------- 1 | import * as qrcode from "qrcode"; 2 | import * as path from "path"; 3 | import { promises as fs } from "fs"; 4 | 5 | async function make(name: string, data: string) { 6 | // Generate QR code data URL 7 | const url = await qrcode.toDataURL(data, { errorCorrectionLevel: "H" }); 8 | 9 | // Strip data URL header and convert to buffer 10 | const buffer = Buffer.from(url.split(",")[1], "base64"); 11 | 12 | // Write buffer to file 13 | await fs.writeFile(path.join(__dirname, `./out/${name}.png`), buffer); 14 | 15 | console.log(`QR code saved as ./out/${name}.png`); 16 | } 17 | 18 | async function main() { 19 | const seed = JSON.parse( 20 | await fs.readFile(path.join(__dirname, `./out/seed.json`), "utf-8") 21 | ); 22 | 23 | seed.map(({ name, data }, i) => { 24 | // 25 | make(`${i + 1}-${name}`, data); 26 | }); 27 | } 28 | 29 | // if main 30 | if (require.main === module) { 31 | main(); 32 | } 33 | -------------------------------------------------------------------------------- /services/assistant-early-access/scripts/out/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | seed.json -------------------------------------------------------------------------------- /services/assistant-early-access/scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scripts", 3 | "dependencies": { 4 | "qrcode": "^1.5.1" 5 | }, 6 | "devDependencies": { 7 | "@types/qrcode": "^1.5.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /services/live-session-auhorize/.env.local: -------------------------------------------------------------------------------- 1 | PUSHER_APP_ID="" 2 | PUSHER_APP_KEY="" 3 | PUSHER_APP_SECRET="" 4 | PUSHER_APP_CLUSTER="" -------------------------------------------------------------------------------- /services/live-session-auhorize/app.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cors from "cors"; 3 | import Pusher from "pusher"; 4 | 5 | const pusher = new Pusher({ 6 | appId: process.env.PUSHER_APP_ID as string, 7 | key: process.env.PUSHER_APP_KEY as string, 8 | secret: process.env.PUSHER_APP_SECRET as string, 9 | cluster: process.env.PUSHER_APP_CLUSTER as string, 10 | useTLS: true, 11 | }); 12 | 13 | const app = express(); 14 | app.use(express.json()); 15 | app.use(express.urlencoded({ extended: true })); 16 | app.use( 17 | cors({ 18 | origin: "*", 19 | }) 20 | ); 21 | 22 | app.get("/", (req, res) => { 23 | res.json({ msg: "service is running" }); 24 | }); 25 | 26 | app.post("/pusher/auth", (req, res) => { 27 | try { 28 | const socketId = req.body.socket_id; 29 | const channel = req.body.channel_name; 30 | const auth = pusher.authenticate(socketId, channel); 31 | res.send(auth); 32 | } catch (_) { 33 | console.error(_); 34 | res.status(400).json({ 35 | error: true, 36 | msg: "Cannot authorize connection outside of pusher interface", 37 | }); 38 | } 39 | }); 40 | 41 | export default app; 42 | -------------------------------------------------------------------------------- /services/live-session-auhorize/handler.ts: -------------------------------------------------------------------------------- 1 | import * as serverlessExpress from "aws-serverless-express"; 2 | import { APIGatewayProxyHandler } from "aws-lambda"; 3 | 4 | import app from "./app"; 5 | 6 | const binaryMimeTypes = [ 7 | "application/javascript", 8 | "application/json", 9 | "application/octet-stream", 10 | "application/xml", 11 | "font/eot", 12 | "font/opentype", 13 | "font/otf", 14 | "image/jpeg", 15 | "image/png", 16 | "image/svg+xml", 17 | "text/comma-separated-values", 18 | "text/css", 19 | "text/html", 20 | "text/javascript", 21 | "text/plain", 22 | "text/text", 23 | "text/xml", 24 | // https://github.com/vendia/serverless-express/blob/master/examples/basic-starter/lambda.js 25 | ]; 26 | 27 | const server = serverlessExpress.createServer(app, null, binaryMimeTypes); 28 | 29 | export const handler: APIGatewayProxyHandler = (event, context) => { 30 | serverlessExpress.proxy(server, event, context); 31 | }; 32 | -------------------------------------------------------------------------------- /services/live-session-auhorize/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transform: { 3 | "^.+\\.tsx?$": "ts-jest", 4 | }, 5 | testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", 6 | testPathIgnorePatterns: ["/lib/", "/node_modules/"], 7 | moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], 8 | collectCoverage: true, 9 | }; 10 | -------------------------------------------------------------------------------- /services/live-session-auhorize/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "preserveConstEnums": true, 4 | "strictNullChecks": true, 5 | "esModuleInterop": true, 6 | "sourceMap": true, 7 | "allowJs": true, 8 | "target": "es5", 9 | "outDir": ".build", 10 | "moduleResolution": "node", 11 | "lib": ["es2015"], 12 | "rootDir": "./" 13 | }, 14 | "exclude": ["__test__", ".build"] 15 | } 16 | -------------------------------------------------------------------------------- /services/live-session-auhorize/webpack.config.js: -------------------------------------------------------------------------------- 1 | const slsw = require("serverless-webpack"); 2 | 3 | module.exports = { 4 | entry: slsw.lib.entries, 5 | plugins: [], 6 | module: { 7 | rules: [ 8 | { 9 | test: /\.ts$/, 10 | loader: "ts-loader", 11 | include: [__dirname], 12 | exclude: /node_modules/, 13 | }, 14 | ], 15 | }, 16 | resolve: { 17 | extensions: [ 18 | ".ts", 19 | ".js", 20 | ".json", // <-- without this, pusher will throw error while resolving. https://github.com/pusher/pusher-http-node/issues/66#issuecomment-389370561 21 | ], 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /sketch/.gitignore: -------------------------------------------------------------------------------- 1 | # build artefacts 2 | assistant.sketchplugin 3 | 4 | # npm 5 | node_modules 6 | .npm 7 | npm-debug.log 8 | 9 | # mac 10 | .DS_Store 11 | 12 | # WebStorm 13 | .idea 14 | 15 | # sketch 16 | # sketch-assets 17 | -------------------------------------------------------------------------------- /sketch/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/sketch/assets/icon.png -------------------------------------------------------------------------------- /sketch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sketch", 3 | "version": "0.1.0", 4 | "engines": { 5 | "sketch": ">=3.0" 6 | }, 7 | "skpm": { 8 | "name": "assistant", 9 | "manifest": "src/manifest.json", 10 | "main": "assistant.sketchplugin", 11 | "assets": [ 12 | "assets/**/*" 13 | ], 14 | "sketch-assets-file": "sketch-assets/icons.sketch" 15 | }, 16 | "scripts": { 17 | "clean": "rimraf assistant.sketchplugin", 18 | "build": "skpm-build", 19 | "watch": "skpm-build --watch", 20 | "start": "skpm-build --watch", 21 | "ready": "yarn run build && skpm-link" 22 | }, 23 | "devDependencies": { 24 | "@skpm/builder": "^0.7.4", 25 | "@skpm/extract-loader": "^2.0.2", 26 | "css-loader": "^3.2.0", 27 | "html-loader": "^0.5.5" 28 | }, 29 | "resources": [ 30 | "resources/**/*.js" 31 | ], 32 | "dependencies": { 33 | "sketch-module-web-view": "^3.1.4" 34 | }, 35 | "author": "softmarshmallow " 36 | } -------------------------------------------------------------------------------- /sketch/resources/style.css: -------------------------------------------------------------------------------- 1 | /* some default styles to make the view more native like */ 2 | 3 | html { 4 | box-sizing: border-box; 5 | background: transparent; 6 | 7 | /* Prevent the page to be scrollable */ 8 | overflow: hidden; 9 | 10 | /* Force the default cursor, even on text */ 11 | cursor: default; 12 | } 13 | 14 | *, *:before, *:after { 15 | box-sizing: inherit; 16 | margin: 0; 17 | padding: 0; 18 | position: relative; 19 | 20 | /* Prevent the content from being selectionable */ 21 | -webkit-user-select: none; 22 | user-select: none; 23 | } 24 | 25 | input, textarea { 26 | -webkit-user-select: auto; 27 | user-select: auto; 28 | } 29 | -------------------------------------------------------------------------------- /sketch/resources/webview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | assistant 6 | 7 | 8 | 9 | assistant 10 | 11 |
12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sketch/resources/webview.js: -------------------------------------------------------------------------------- 1 | // disable the context menu (eg. the right click menu) to have a more native feel 2 | document.addEventListener('contextmenu', (e) => { 3 | e.preventDefault() 4 | }) 5 | 6 | // call the plugin from the webview 7 | document.getElementById('button').addEventListener('click', () => { 8 | window.postMessage('nativeLog', 'Called from the webview') 9 | }) 10 | 11 | // call the webview from the plugin 12 | window.setRandomNumber = (randomNumber) => { 13 | document.getElementById('answer').innerHTML = 'Random number from the plugin: ' + randomNumber 14 | } 15 | -------------------------------------------------------------------------------- /sketch/sketch-assets/icons.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/sketch/sketch-assets/icons.sketch -------------------------------------------------------------------------------- /sketch/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "compatibleVersion": 3, 3 | "bundleVersion": 1, 4 | "commands": [ 5 | { 6 | "name": "my-command", 7 | "identifier": "assistant.my-command-identifier", 8 | "script": "./my-command.js", 9 | "handlers": { 10 | "run": "onRun", 11 | "actions": { 12 | "Shutdown": "onShutdown" 13 | } 14 | } 15 | } 16 | ], 17 | "menu": { 18 | "title": "assistant", 19 | "items": [ 20 | "assistant.my-command-identifier" 21 | ] 22 | } 23 | } -------------------------------------------------------------------------------- /sketch/webpack.skpm.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (config, entry) { 2 | config.node = entry.isPluginCommand ? false : { 3 | setImmediate: false 4 | }; 5 | config.module.rules.push({ 6 | test: /\.(html)$/, 7 | use: [{ 8 | loader: "@skpm/extract-loader", 9 | }, 10 | { 11 | loader: "html-loader", 12 | options: { 13 | attrs: [ 14 | 'img:src', 15 | 'link:href' 16 | ], 17 | interpolate: true, 18 | }, 19 | }, 20 | ] 21 | }) 22 | config.module.rules.push({ 23 | test: /\.(css)$/, 24 | use: [{ 25 | loader: "@skpm/extract-loader", 26 | }, 27 | { 28 | loader: "css-loader", 29 | }, 30 | ] 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # We are looking for contributors to make tests 2 | 3 | the only tests we currenly have is running webpack build for figma assistant. 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": ["es6", "dom", "es2017"], 5 | "outDir": "dist", 6 | "jsx": "react", 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true, 9 | "allowSyntheticDefaultImports": true, 10 | "removeComments": true, 11 | "noImplicitAny": false, 12 | "moduleResolution": "node", 13 | "typeRoots": ["./node_modules/@types", "./node_modules/@figma"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /web/.env: -------------------------------------------------------------------------------- 1 | # This is a GIT Included .env file. - why? - to specify `NEXT_PUBLIC_HOSTED=true`. (Use .env.local to override values) 2 | 3 | NEXT_PUBLIC_HOSTED=true 4 | NEXT_PUBLIC_FIGMA_PERSONAL_ACCESS_TOKEN= 5 | NEXT_PUBLIC_BRIDGED_FIRST_PARTY_ANALYTICS_PROXY_SERVICE_TOTP_SECRET=00000000 6 | NEXT_PUBLIC_GRIDA_FIRST_PARTY_PROXY_AUTH_REQUEST_TOTP_SECRET=00000000 7 | NEXT_PUBLIC_UNSPLASH_TMP_LOCAL_CLIENT_ID= 8 | NEXT_PUBLIC_PUSHER_APP_KEY= 9 | NEXT_PUBLIC_PUSHER_APP_CLUSTER= 10 | NEXT_PUBLIC_CORS_GRIDA_API_KEY=get-it-from-https://github.com/gridaco/base/issues/23 11 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | # Grida Assistant on Web (Webdev) 2 | 3 | > this project is for inspecting and developing the ui package, and running the tests. 4 | 5 | ![grida assistant running on chrome as webdev](../docs/images/assistant-webdev-example.png) 6 | 7 | ## Getting Started 8 | 9 | First, run the development server: 10 | 11 | ```bash 12 | npm run dev 13 | # or 14 | yarn dev 15 | ``` 16 | 17 | Open [http://localhost:3303](http://localhost:3303) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 20 | -------------------------------------------------------------------------------- /web/lib/gtag.js: -------------------------------------------------------------------------------- 1 | export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_ID; 2 | 3 | // https://developers.google.com/analytics/devguides/collection/gtagjs/pages 4 | export const pageview = (url) => { 5 | window.gtag("config", GA_TRACKING_ID, { 6 | page_path: url, 7 | }); 8 | }; 9 | 10 | // https://developers.google.com/analytics/devguides/collection/gtagjs/events 11 | export const event = ({ action, category, label, value }) => { 12 | window.gtag("event", action, { 13 | event_category: category, 14 | event_label: label, 15 | value: value, 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev -p 3303", 7 | "build": "next build", 8 | "start": "next start -p 3303" 9 | }, 10 | "dependencies": { 11 | "app": "0.0.1", 12 | "languagedetect": "^2.0.0", 13 | "next": "^13.1.6", 14 | "openai": "^3.1.0", 15 | "pusher": "^5.0.0", 16 | "react": "^18.2.0", 17 | "react-dom": "^18.2.0" 18 | }, 19 | "devDependencies": { 20 | "@types/react": "^18.0.28", 21 | "typescript": "4.3.5" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import type { AppProps } from "next/app"; 3 | import { useRouter } from "next/router"; 4 | import * as gtag from "../lib/gtag"; 5 | 6 | function WebApp({ Component, pageProps }: AppProps) { 7 | // region GA 8 | const router = useRouter(); 9 | useEffect(() => { 10 | const handleRouteChange = (url) => { 11 | gtag.pageview(url); 12 | }; 13 | router.events.on("routeChangeComplete", handleRouteChange); 14 | return () => { 15 | router.events.off("routeChangeComplete", handleRouteChange); 16 | }; 17 | }, [router.events]); 18 | // endregion GA 19 | 20 | return ; 21 | } 22 | export default WebApp; 23 | -------------------------------------------------------------------------------- /web/pages/api/live-session/auth.ts: -------------------------------------------------------------------------------- 1 | import Pusher from "pusher"; 2 | 3 | const pusher = new Pusher({ 4 | appId: process.env.PUSHER_APP_ID as string, 5 | key: process.env.PUSHER_APP_KEY as string, 6 | secret: process.env.PUSHER_APP_SECRET as string, 7 | cluster: process.env.PUSHER_APP_CLUSTER as string, 8 | useTLS: true, 9 | }); 10 | 11 | export default function handler(req, res) { 12 | switch (req.method) { 13 | case "GET": { 14 | res.json({ msg: "hi" }); 15 | } 16 | } 17 | const socketId = req.body.socket_id; 18 | const channel = req.body.channel_name; 19 | const auth = pusher.authenticate(socketId, channel); 20 | res.send(auth); 21 | } 22 | -------------------------------------------------------------------------------- /web/pages/api/translation/detect.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | import { detectLanguage } from "service/translation"; 4 | 5 | export default async function handler( 6 | req: NextApiRequest, 7 | res: NextApiResponse 8 | ) { 9 | const q = req.query.q as string; 10 | 11 | const { lang, confidence } = await detectLanguage(q); 12 | 13 | switch (req.method) { 14 | case "GET": 15 | res.status(200).json({ 16 | q: q, 17 | lang: lang, 18 | confidence: confidence, 19 | }); 20 | break; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import App from "app/lib/main"; 4 | import { useEffect } from "react"; 5 | import { PluginSdkService } from "@plugin-sdk/service"; 6 | import { TargetPlatform } from "@plugin-sdk/core"; 7 | import { useRouter } from "next/router"; 8 | import { get_target_platform_from_query } from "../utils/platform-init-query"; 9 | 10 | export default function IndexPage() { 11 | const router = useRouter(); 12 | 13 | const platform = get_target_platform_from_query( 14 | router.query["platform"] as string 15 | ); 16 | 17 | useEffect(() => { 18 | window.addEventListener("message", (rev) => { 19 | if (platform == TargetPlatform.webdev) { 20 | if (rev.data.pluginMessage) { 21 | PluginSdkService.handle(rev.data.pluginMessage); 22 | } 23 | } 24 | }); 25 | }, []); 26 | 27 | return ; 28 | } 29 | -------------------------------------------------------------------------------- /web/pages/init-figma.tsx: -------------------------------------------------------------------------------- 1 | import App from "app/lib/main"; 2 | import { TargetPlatform } from "@plugin-sdk/core"; 3 | 4 | export default function FigmaInitTriggerPage() { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /web/pages/init-webdev.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import App from "app/lib/main"; 3 | import { PluginSdkService } from "@plugin-sdk/service"; 4 | import { TargetPlatform } from "@plugin-sdk/core"; 5 | 6 | export default function InitWebdevTriggerPage() { 7 | useEffect(() => { 8 | window.addEventListener("message", (rev) => { 9 | if (rev.data.pluginMessage) { 10 | PluginSdkService.handle(rev.data.pluginMessage); 11 | } 12 | }); 13 | }, []); 14 | 15 | return ; 16 | } 17 | -------------------------------------------------------------------------------- /web/public/_/early-access/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/_/early-access/background.png -------------------------------------------------------------------------------- /web/public/assets/images/artwork-app-grouped-figma-grida-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/assets/images/artwork-app-grouped-figma-grida-vscode.png -------------------------------------------------------------------------------- /web/public/assets/images/artwork-figma-desktop-where-is-share-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/assets/images/artwork-figma-desktop-where-is-share-button.png -------------------------------------------------------------------------------- /web/public/assets/images/empty-state-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/assets/images/empty-state-icon.png -------------------------------------------------------------------------------- /web/public/assets/images/mac-icon-grida.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/assets/images/mac-icon-grida.png -------------------------------------------------------------------------------- /web/public/assets/images/mac-icon-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/assets/images/mac-icon-vscode.png -------------------------------------------------------------------------------- /web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/web/public/favicon.ico -------------------------------------------------------------------------------- /web/service/providers/openai.ts: -------------------------------------------------------------------------------- 1 | import { Configuration, OpenAIApi } from "openai"; 2 | 3 | const OPENAI_API_SECRET_KEY = process.env.OPENAI_API_SECRET_KEY; 4 | const configuration = new Configuration({ 5 | apiKey: OPENAI_API_SECRET_KEY, 6 | }); 7 | 8 | const openai = new OpenAIApi(configuration); 9 | 10 | export default openai; 11 | -------------------------------------------------------------------------------- /web/service/translation/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./detect"; 2 | -------------------------------------------------------------------------------- /web/service/translation/translate-for-text-to-image.ts: -------------------------------------------------------------------------------- 1 | import openai from "service/providers/openai"; 2 | import { detectLanguage } from "./detect"; 3 | 4 | const propmpt = ( 5 | text: string 6 | ) => `Translate this text-to-image prompt to English for better results: 7 | Prompt: ${text} 8 | Output: `; 9 | 10 | export async function translateForTextToImage(text: string) { 11 | const { lang } = await detectLanguage(text); 12 | 13 | if (lang === "en") { 14 | return text; 15 | } else { 16 | // translate text to english. 17 | const { data } = await openai.createCompletion({ 18 | model: "text-davinci-003", 19 | prompt: propmpt(text), 20 | n: 1, 21 | }); 22 | 23 | const { choices } = data; 24 | 25 | return choices[0].text.trim(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /web/service/translation/translate.ts: -------------------------------------------------------------------------------- 1 | import openai from "service/providers/openai"; 2 | 3 | export function translate( 4 | text: string, 5 | config: { 6 | origin?: string; 7 | target: string; 8 | } 9 | ) { 10 | // 11 | // openai.createCompletion({}); 12 | } 13 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "downlevelIteration": true, 14 | "noEmit": true, 15 | "esModuleInterop": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "baseUrl": ".", 20 | "isolatedModules": true, 21 | "jsx": "preserve", 22 | "incremental": true 23 | }, 24 | "include": [ 25 | "next-env.d.ts", 26 | "**/*.ts", 27 | "**/*.tsx" 28 | ], 29 | "exclude": [ 30 | "node_modules" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /web/utils/platform-init-query.ts: -------------------------------------------------------------------------------- 1 | import { TargetPlatform } from "@plugin-sdk/core"; 2 | 3 | export function get_target_platform_from_query(platform: string) { 4 | switch (platform) { 5 | case "figma": 6 | return TargetPlatform.figma; 7 | case "webdev": 8 | return TargetPlatform.webdev; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /xd/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist -------------------------------------------------------------------------------- /xd/debug.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 30003, 3 | "breakOnStart": false 4 | } -------------------------------------------------------------------------------- /xd/images/icon@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/xd/images/icon@1x.png -------------------------------------------------------------------------------- /xd/images/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/xd/images/icon@2x.png -------------------------------------------------------------------------------- /xd/images/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/xd/images/icon@3x.png -------------------------------------------------------------------------------- /xd/images/icon@4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/xd/images/icon@4x.png -------------------------------------------------------------------------------- /xd/images/icon@5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/xd/images/icon@5x.png -------------------------------------------------------------------------------- /xd/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id":"f72154ff", 3 | "name": "Bridged", 4 | "version": "2020.0.1", 5 | "icons": [ 6 | { 7 | "width": 24, 8 | "height": 24, 9 | "path": "images/icon@1x.png" 10 | }, 11 | { 12 | "width": 48, 13 | "height": 48, 14 | "path": "images/icon@2x.png" 15 | } 16 | ], 17 | "host": { 18 | "app": "XD", 19 | "minVersion": "25.0" 20 | }, 21 | "uiEntryPoints": [ 22 | { 23 | "type": "panel", 24 | "label": "UI Panel", 25 | "panelId": "flutterPanel" 26 | }, 27 | { 28 | "type": "menu", 29 | "label": "Export All Widgets", 30 | "commandId": "exportAll", 31 | "shortcut": { 32 | "mac": "Cmd+Shift+F", 33 | "win": "Ctrl+Shift+F" 34 | } 35 | }, 36 | { 37 | "type": "menu", 38 | "label": "Export Selected Widget", 39 | "commandId": "exportSelected", 40 | "shortcut": { 41 | "mac": "Cmd+Shift+Alt+1", 42 | "win": "Ctrl+Shift+Alt+1" 43 | } 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /xd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xd", 3 | "author": "bridged.xyz authors", 4 | "repository": "https://github.com/bridgedxyz/assistant", 5 | "license": "BRGD", 6 | "version": "0.0.1", 7 | "main": "main", 8 | "scripts": { 9 | "build": "webpack", 10 | "deploy": "node scripts/deploy" 11 | }, 12 | "dependencies": { 13 | "app": "0.0.1" 14 | }, 15 | "devDependencies": { 16 | "archiver": "^3.1.1", 17 | "css-loader": "^5.0.1", 18 | "ncp": "^2.0.0", 19 | "style-loader": "^2.0.0", 20 | "url-loader": "^4.1.1", 21 | "webpack": "^4.38.0", 22 | "webpack-cli": "^4.4.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /xd/src/lib/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridaco/assistant/5ad38fb22fa5fdf5e01ccb1272f871d02cb2c3e7/xd/src/lib/index.js -------------------------------------------------------------------------------- /xd/src/ui/main.tsx: -------------------------------------------------------------------------------- 1 | const { editDocument } = require("application"); 2 | const os = require("os"); 3 | const xd = require("scenegraph"); 4 | import ReactDOM from "react-dom"; 5 | import React from "react"; 6 | 7 | class Notifier { 8 | f; 9 | listen(f) { 10 | this.f = f; 11 | } 12 | notify(o) { 13 | this.f && this.f(o); 14 | } 15 | } 16 | 17 | let panelHolder, 18 | notifier = new Notifier(); 19 | 20 | function create() { 21 | if (panelHolder == null) { 22 | panelHolder = document.createElement("div"); 23 | update(); 24 | } 25 | return panelHolder; 26 | } 27 | 28 | function show(event) { 29 | if (!panelHolder) event.node.appendChild(create()); 30 | } 31 | 32 | function update(selection?) { 33 | let items = selection && selection.items; 34 | ReactDOM.render(

replace content here

, panelHolder); 35 | // render(< key='panel' selected={items} notifier={notifier} />, ); 36 | } 37 | 38 | module.exports = { 39 | panels: { 40 | flutterPanel: { 41 | show, 42 | update, 43 | }, 44 | }, 45 | commands: { 46 | // exportAll, 47 | // exportSelected, 48 | }, 49 | }; 50 | -------------------------------------------------------------------------------- /xd/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "lib": [ 6 | "es2017", 7 | "es7", 8 | "es6", 9 | "dom" 10 | ], 11 | "jsx": "react", 12 | "esModuleInterop": true, 13 | "outDir": "dist", 14 | "declaration": true, 15 | "allowSyntheticDefaultImports": true, 16 | "sourceMap": true, 17 | "experimentalDecorators": true, 18 | "noUnusedLocals": false, 19 | "typeRoots": [ 20 | "./node_modules/@types", 21 | "../node_modules/@types", 22 | // remove this when design-sdk fully supports xd. 23 | // this is required at this point. 24 | "../node_modules/@figma", 25 | ] 26 | }, 27 | "exclude": [ 28 | "node_modules", 29 | "dist", 30 | "build", 31 | "example", 32 | "tests" 33 | ] 34 | } -------------------------------------------------------------------------------- /zeplin/.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | node_modules 4 | .DS_Store 5 | Thumbs.db 6 | npm-debug.log* 7 | /dist 8 | -------------------------------------------------------------------------------- /zeplin/README.md: -------------------------------------------------------------------------------- 1 | # Bridged zeplin extension is not yet under development. 2 | 3 | 4 | 5 | zeplin extension for birdged 6 | 7 | ## Getting started 8 | 9 | Add the extension to your project from [extensions.zeplin.io](https://extensions.zeplin.io). 10 | 11 | 18 | 19 | 27 | 28 | ## Development 29 | 30 | This extension is developed using [zem](https://github.com/zeplin/zem), Zeplin Extension Manager. zem is a command line tool that lets you quickly create, test and publish extensions. 31 | 32 | To learn more about creating Zeplin extensions, [see documentation](https://github.com/zeplin/zeplin-extension-documentation). 33 | -------------------------------------------------------------------------------- /zeplin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zeplin", 3 | "version": "0.1.0", 4 | "description": "zeplin extension for birdged", 5 | "license": "https://github.com/bridgedxyz/contributing-and-license", 6 | "scripts": { 7 | "start": "zem start", 8 | "build": "zem build", 9 | "clean": "zem clean", 10 | "exec": "zem exec", 11 | "test": "zem test", 12 | "publish": "zem publish" 13 | }, 14 | "zeplin": { 15 | "displayName": "Bridged", 16 | "platforms": [ 17 | "web", 18 | "android", 19 | "ios", 20 | "osx" 21 | ] 22 | }, 23 | "dependencies": { 24 | "zem": "^1.0.6" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /zeplin/src/fixtures/components.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Simple Component", 4 | "description": "" 5 | }, 6 | { 7 | "name": "Component with description", 8 | "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lacus magna, elementum vel orci a, ornare molestie augue. Fusce semper pharetra augue ac condimentum. Suspendisse eget varius nulla. Vivamus feugiat ligula nec volutpat tincidunt. Curabitur iaculis purus convallis, scelerisque nulla vitae, condimentum ante. Curabitur vehicula nunc in massa congue, quis varius metus placerat. Integer feugiat, orci eu sagittis interdum, tortor nulla pulvinar mauris, egestas suscipit eros orci sit amet sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus." 9 | } 10 | ] -------------------------------------------------------------------------------- /zeplin/src/fixtures/index.js: -------------------------------------------------------------------------------- 1 | import { Context, Screen, Version, Component } from "@zeplin/extension-model"; 2 | 3 | import project from "./project.json"; 4 | import screensData from "./screens.json"; 5 | import componentsData from "./components.json"; 6 | import versionData from "./version.json"; 7 | import { zeplin } from "../../package.json"; 8 | 9 | const defaultOptions = zeplin.options.reduce((options, option) => { 10 | options[option.id] = option.default; 11 | return options; 12 | }, {}); 13 | 14 | export const context = new Context({ project, options: defaultOptions }); 15 | export const version = new Version(versionData); 16 | export const screens = screensData.map(data => new Screen(data)); 17 | export const components = componentsData.map(data => new Component(data)); 18 | -------------------------------------------------------------------------------- /zeplin/src/fixtures/screens.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Simple screen", 4 | "description": "", 5 | "tags": [] 6 | }, 7 | { 8 | "name": "Screen with description", 9 | "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lacus magna, elementum vel orci a, ornare molestie augue. Fusce semper pharetra augue ac condimentum. Suspendisse eget varius nulla. Vivamus feugiat ligula nec volutpat tincidunt. Curabitur iaculis purus convallis, scelerisque nulla vitae, condimentum ante. Curabitur vehicula nunc in massa congue, quis varius metus placerat. Integer feugiat, orci eu sagittis interdum, tortor nulla pulvinar mauris, egestas suscipit eros orci sit amet sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.", 10 | "tags": [] 11 | }, 12 | { 13 | "name": "Screen with 3 tags", 14 | "description": "", 15 | "tags": ["First tag", "Second tag", "Third tag"] 16 | } 17 | ] --------------------------------------------------------------------------------