├── .browserslistrc ├── compiler ├── index.js ├── platforms │ ├── preact.js │ ├── solid.js │ ├── react.js │ ├── webcomponents.js │ ├── angular.js │ ├── svelte.js │ └── qwik.js ├── themes.tasks.js ├── dev.tasks.js └── compiler.tasks.js ├── src ├── typings │ └── styles.d.ts ├── styles │ ├── mixins │ │ ├── shared.css │ │ ├── background-opacity.css │ │ └── breakpoint-modifier.css │ ├── base │ │ └── reset.css │ ├── themes │ │ ├── papanasi │ │ │ ├── container.css │ │ │ ├── row.css │ │ │ ├── column.css │ │ │ ├── index.css │ │ │ ├── tooltip.css │ │ │ ├── pill.css │ │ │ ├── avatar.css │ │ │ ├── itchio.css │ │ │ ├── variables.css │ │ │ ├── code.css │ │ │ ├── spinner.css │ │ │ └── button.css │ │ └── sketch │ │ │ ├── container.css │ │ │ ├── row.css │ │ │ ├── column.css │ │ │ ├── index.css │ │ │ ├── tooltip.css │ │ │ ├── itchio.css │ │ │ ├── variables.css │ │ │ ├── code.css │ │ │ ├── avatar.css │ │ │ ├── pill.css │ │ │ └── spinner.css │ ├── build.css │ └── variables.css ├── elements │ ├── layout │ │ ├── row │ │ │ ├── index.ts │ │ │ ├── row.model.ts │ │ │ ├── row.css │ │ │ ├── row.service.ts │ │ │ ├── row.lite.tsx │ │ │ └── row.stories.mdx │ │ ├── column │ │ │ ├── index.ts │ │ │ ├── column.model.ts │ │ │ ├── column.service.ts │ │ │ ├── column.lite.tsx │ │ │ ├── column.css │ │ │ └── grid.stories.mdx │ │ └── container │ │ │ ├── index.ts │ │ │ ├── container.model.ts │ │ │ ├── container.css │ │ │ ├── container.service.ts │ │ │ ├── container.lite.tsx │ │ │ └── container.stories.mdx │ ├── components │ │ ├── code │ │ │ ├── index.ts │ │ │ ├── code.css │ │ │ ├── code.model.ts │ │ │ └── code.lite.tsx │ │ ├── pill │ │ │ ├── index.ts │ │ │ ├── pill.css │ │ │ ├── pill.model.ts │ │ │ ├── pill.service.ts │ │ │ ├── pill.lite.tsx │ │ │ └── pill.stories.mdx │ │ ├── avatar │ │ │ ├── index.ts │ │ │ ├── avatar.model.ts │ │ │ ├── avatar.css │ │ │ ├── avatar.lite.tsx │ │ │ └── avatar.service.ts │ │ ├── button │ │ │ ├── index.ts │ │ │ ├── button.model.ts │ │ │ ├── button.css │ │ │ ├── button.lite.tsx │ │ │ └── button.service.ts │ │ ├── spinner │ │ │ ├── index.ts │ │ │ ├── spinner.model.ts │ │ │ ├── spinner.service.ts │ │ │ ├── spinner.lite.tsx │ │ │ ├── spinner.css │ │ │ └── spinner.stories.mdx │ │ └── breadcrumb │ │ │ ├── index.ts │ │ │ ├── breadcrumb.service.ts │ │ │ ├── breadcrumb.model.ts │ │ │ ├── breadcrumb.css │ │ │ ├── breadcrumb.lite.tsx │ │ │ └── breadcrumb.stories.mdx │ ├── enterprise │ │ └── itchio │ │ │ ├── index.ts │ │ │ ├── itchio.css │ │ │ ├── itchio.model.ts │ │ │ ├── itchio.service.ts │ │ │ ├── itchio.lite.tsx │ │ │ └── itchio.stories.mdx │ └── extensions │ │ ├── tooltip │ │ ├── index.ts │ │ ├── tooltip.css │ │ └── tooltip.stories.mdx │ │ └── toast │ │ ├── toast.css │ │ ├── index.ts │ │ ├── toast.model.ts │ │ ├── toast.bus.ts │ │ ├── toast.service.ts │ │ ├── toast.hook.ts │ │ ├── toast.lite.tsx │ │ └── toast.stories.mdx ├── models │ ├── dynamic.model.ts │ ├── external-library.model.ts │ ├── index.ts │ ├── variant.model.ts │ ├── intent.model.ts │ ├── component.model.ts │ └── breakpoint.model.ts ├── helpers │ ├── object.helper.ts │ ├── version.helper.ts │ ├── classes.helper.ts │ ├── arg-type.helper.ts │ ├── index.ts │ ├── debug.helper.ts │ ├── platform.helper.ts │ ├── wait.helper.ts │ ├── code.helper.ts │ ├── itchio.helper.ts │ ├── element.helper.ts │ ├── inject-script.helper.ts │ ├── color.helper.ts │ └── breakpoint.helper.ts └── index.ts ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── component-request.md │ └── bug_report.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── azure-static-web-apps-witty-plant-07a086e03.yml ├── .storybook ├── helpers │ ├── index.ts │ └── codesandbox │ │ ├── index.ts │ │ ├── codesandbox-preact.helper.ts │ │ ├── codesandbox-react.helper.ts │ │ ├── codesandbox-qwik.helper.ts │ │ ├── codesandbox-solid.helper.ts │ │ ├── codesandbox-vue.helper.ts │ │ ├── codesandbox-svelte.helper.ts │ │ ├── codesandbox-web.helper.ts │ │ ├── codesandbox.helper.ts │ │ └── codesandbox-angular.helper.ts ├── components │ ├── index.ts │ ├── customization.css │ └── Codesandbox.tsx ├── manager.js ├── initialize.js ├── theme.js └── main.cjs ├── packages ├── solid │ ├── solid-index.tsx │ ├── rollup.config.js │ ├── copy-css.js │ └── package.json ├── vue │ ├── typings │ │ └── vue.d.ts │ ├── rollup.config.js │ └── package.json ├── svelte │ ├── svelte.config.js │ ├── tsconfig.json │ └── package.json ├── webcomponents │ ├── rollup.config.js │ └── package.json ├── angular │ ├── rollup.config.js │ └── package.json ├── react │ ├── rollup.config.js │ └── package.json ├── preact │ ├── rollup.config.js │ └── package.json └── qwik │ ├── vite.config.ts │ ├── tsconfig.json │ └── package.json ├── docs ├── resources │ └── favicon.ico ├── _introduction.stories.mdx └── elements.stories.mdx ├── sponsors └── logos │ └── helpdev.png ├── .ncurc.json ├── .prettierrc.json ├── .editorconfig ├── lerna.json ├── .gitignore ├── hooks ├── post-package.hook.js └── post-install.hook.js ├── rollup.themes.config.js ├── tsconfig.json ├── postcss.config.cjs ├── .stylelintrc ├── LICENSE.md ├── .eslintrc.cjs ├── SPONSORS.md ├── CONTRIBUTING.md ├── AGENTS.md ├── rollup.config.js └── CODE-OF-CONDUCT.md /.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 versions 2 | -------------------------------------------------------------------------------- /compiler/index.js: -------------------------------------------------------------------------------- 1 | import './compiler.tasks.js'; 2 | -------------------------------------------------------------------------------- /src/typings/styles.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css' {} 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [ckgrafico, BuilderIO] 2 | -------------------------------------------------------------------------------- /.storybook/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './codesandbox'; 2 | -------------------------------------------------------------------------------- /packages/solid/solid-index.tsx: -------------------------------------------------------------------------------- 1 | export * from './src/index.ts'; 2 | -------------------------------------------------------------------------------- /src/styles/mixins/shared.css: -------------------------------------------------------------------------------- 1 | @define-mixin shared-styles { 2 | } 3 | -------------------------------------------------------------------------------- /src/styles/base/reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | -------------------------------------------------------------------------------- /src/elements/layout/row/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './row.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/components/code/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './code.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/components/pill/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './pill.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/layout/column/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './column.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/components/avatar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './avatar.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/components/button/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './button.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/components/spinner/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './spinner.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/enterprise/itchio/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './itchio.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/extensions/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './tooltip.hook'; 2 | -------------------------------------------------------------------------------- /src/elements/layout/container/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './container.lite'; 2 | -------------------------------------------------------------------------------- /src/elements/components/breadcrumb/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './breadcrumb.lite'; 2 | -------------------------------------------------------------------------------- /.storybook/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Codesandbox'; 2 | export * from './Customization'; 3 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-toast { 4 | } 5 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/container.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-container { 4 | } 5 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/container.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-container { 4 | } 5 | -------------------------------------------------------------------------------- /docs/resources/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CKGrafico/papanasi/HEAD/docs/resources/favicon.ico -------------------------------------------------------------------------------- /sponsors/logos/helpdev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CKGrafico/papanasi/HEAD/sponsors/logos/helpdev.png -------------------------------------------------------------------------------- /src/styles/themes/papanasi/row.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-row { 4 | @mixin shared-styles; 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/row.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-row { 4 | @mixin shared-styles; 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/column.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-column { 4 | @mixin shared-styles; 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/column.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-column { 4 | @mixin shared-styles; 5 | } 6 | -------------------------------------------------------------------------------- /src/models/dynamic.model.ts: -------------------------------------------------------------------------------- 1 | // We don't want to limit the user to use only our types 2 | 3 | export type Dynamic = T | string; 4 | -------------------------------------------------------------------------------- /src/models/external-library.model.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 2 | export type ExternalLibrary = any; 3 | -------------------------------------------------------------------------------- /packages/vue/typings/vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { defineComponent } from 'vue'; 3 | export default defineComponent; 4 | } 5 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useToastExtension } from './toast.hook'; 2 | export { default } from './toast.lite'; 3 | -------------------------------------------------------------------------------- /.ncurc.json: -------------------------------------------------------------------------------- 1 | { 2 | "reject": [ 3 | "mini-css-extract-plugin", 4 | "ora", 5 | "typescript", 6 | "@storybook/*", 7 | "glob" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/styles/build.css: -------------------------------------------------------------------------------- 1 | @import './mixins/shared.css'; 2 | @import './mixins/breakpoint-modifier.css'; 3 | @import './mixins/background-opacity.css'; 4 | 5 | @import './base/reset.css'; 6 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "bracketSpacing": true, 6 | "trailingComma": "none", 7 | "printWidth": 120, 8 | "endOfLine": "auto" 9 | } -------------------------------------------------------------------------------- /src/elements/extensions/tooltip/tooltip.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-tooltip { 4 | position: absolute; 5 | display: flex; 6 | justify-content: center; 7 | z-index: 1; 8 | } 9 | -------------------------------------------------------------------------------- /packages/svelte/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | 3 | const config = { 4 | kit: { 5 | adapter: adapter() 6 | } 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /src/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './breakpoint.model'; 2 | export * from './component.model'; 3 | export * from './dynamic.model'; 4 | export * from './external-library.model'; 5 | export * from './intent.model'; 6 | export * from './variant.model'; 7 | -------------------------------------------------------------------------------- /src/helpers/object.helper.ts: -------------------------------------------------------------------------------- 1 | // Meanwhile we have Ts types problems on compiling, this is a safe way to get values from an object 2 | export function getObjectValue(object, property) { 3 | return object && object[property] ? object[property] : null; 4 | } 5 | -------------------------------------------------------------------------------- /src/styles/mixins/background-opacity.css: -------------------------------------------------------------------------------- 1 | @define-mixin background-opacity $color, $opacity { 2 | background-image: linear-gradient( 3 | to bottom, 4 | $color calc(($opacity - 1) * 10000%), 5 | transparent calc($opacity * 10000%) 6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /packages/webcomponents/rollup.config.js: -------------------------------------------------------------------------------- 1 | import config from '../../rollup.config.js'; 2 | import packageJson from './package.json' assert { type: 'json' }; 3 | 4 | export default config({ 5 | dir: './packages/webcomponents', 6 | packageJson, 7 | dts: false 8 | }); 9 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | import { initialize } from './initialize'; 3 | import './storybook.css'; 4 | import { Themes } from './theme'; 5 | 6 | addons.setConfig({ 7 | theme: Themes.manager 8 | }); 9 | 10 | initialize(); 11 | -------------------------------------------------------------------------------- /src/models/variant.model.ts: -------------------------------------------------------------------------------- 1 | export enum Variant { 2 | Basic = '', 3 | Primary = 'primary', 4 | Secondary = 'secondary', 5 | Tertiary = 'tertiary' 6 | } 7 | 8 | export const variants = Object.entries(Variant).map(([key, value]: [string, string]) => ({ key, value })); 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /docs/_introduction.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Description } from '@storybook/addon-docs'; 2 | import Readme from '../README.md'; 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "command": { 4 | "publish": { 5 | "conventionalCommits": true, 6 | "ignoreChanges": ["*.md", "stats.html", ".spec.ts", ".stories.ts"] 7 | } 8 | }, 9 | "packages": ["packages/*"], 10 | "version": "1.1.2" 11 | } 12 | -------------------------------------------------------------------------------- /src/models/intent.model.ts: -------------------------------------------------------------------------------- 1 | export enum Intent { 2 | None = '', 3 | Info = 'info', 4 | Success = 'warning', 5 | Warning = 'success', 6 | Error = 'error' 7 | } 8 | 9 | export const intents = Object.entries(Intent).map(([key, value]: [string, string]) => ({ key, value })); 10 | -------------------------------------------------------------------------------- /src/styles/mixins/breakpoint-modifier.css: -------------------------------------------------------------------------------- 1 | /* We are using a class because nowadays you cannot have a custom property in a media query */ 2 | @define-mixin breakpoint-modifier $breakpoint, $value { 3 | body.breakpoint-$(breakpoint) &--$(value)\@$(breakpoint) { 4 | @mixin-content; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.storybook/initialize.js: -------------------------------------------------------------------------------- 1 | import favicon from '../docs/resources/favicon.ico'; 2 | 3 | export function initialize() { 4 | const link = document.createElement('link'); 5 | link.setAttribute('rel', 'shortcut icon'); 6 | link.setAttribute('href', favicon); 7 | document.head.appendChild(link); 8 | } 9 | -------------------------------------------------------------------------------- /compiler/platforms/preact.js: -------------------------------------------------------------------------------- 1 | import compiler from '../base.compiler.js'; 2 | 3 | const DEFAULT_OPTIONS = { 4 | target: 'preact', 5 | extension: 'tsx', 6 | state: 'useState', 7 | styles: 'style-tag' 8 | }; 9 | 10 | (async () => { 11 | await compiler.compile({ ...DEFAULT_OPTIONS }); 12 | })(); 13 | -------------------------------------------------------------------------------- /packages/angular/rollup.config.js: -------------------------------------------------------------------------------- 1 | import config from '../../rollup.config.js'; 2 | import packageJson from './package.json' assert { type: 'json' }; 3 | 4 | export default config({ 5 | dir: './packages/angular', 6 | packageJson, 7 | cancelBrowserListForTypescript: true, 8 | dts: false 9 | }); 10 | -------------------------------------------------------------------------------- /src/elements/layout/container/container.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState } from '~/models'; 2 | 3 | export interface ContainerProps extends BaseProps { 4 | fluid?: boolean; 5 | centered?: boolean; 6 | } 7 | 8 | export interface ContainerState extends BaseState { 9 | classes: { base: string }; 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packages/**/dist/ 3 | packages/**/lib/ 4 | packages/**/src/ 5 | packages/**/types/ 6 | packages/**/tsconfig.* 7 | *.log 8 | storybook-static/ 9 | packages/webcomponents/custom-elements.json 10 | **/stats.html 11 | packages/svelte/.svelte-kit 12 | packages/qwik/tsconfig.tsbuildinfo 13 | .themes/ 14 | -------------------------------------------------------------------------------- /src/helpers/version.helper.ts: -------------------------------------------------------------------------------- 1 | import { debug } from './debug.helper'; 2 | 3 | let version = '0.0.0'; 4 | 5 | export function setVersion(newVersion: string) { 6 | debug(`Setting new platform ${newVersion}`); 7 | 8 | version = newVersion; 9 | } 10 | 11 | export function getVersion(): string { 12 | return version; 13 | } 14 | -------------------------------------------------------------------------------- /src/elements/components/pill/pill.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-pill { 4 | --pa-pill-text-size: var(--pa-font-size-small); 5 | 6 | display: inline-flex; 7 | justify-content: center; 8 | align-content: center; 9 | font-size: var(--pa-pill-text-size); 10 | padding: 0.2rem 0.45rem; 11 | text-align: center; 12 | } 13 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/index.css: -------------------------------------------------------------------------------- 1 | @import './variables.css'; 2 | @import './button.css'; 3 | @import './avatar.css'; 4 | @import './code.css'; 5 | @import './column.css'; 6 | @import './container.css'; 7 | @import './row.css'; 8 | @import './itchio.css'; 9 | @import './pill.css'; 10 | @import './spinner.css'; 11 | @import './tooltip.css'; 12 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/index.css: -------------------------------------------------------------------------------- 1 | @import './variables.css'; 2 | @import './button.css'; 3 | @import './avatar.css'; 4 | @import './code.css'; 5 | @import './column.css'; 6 | @import './container.css'; 7 | @import './row.css'; 8 | @import './itchio.css'; 9 | @import './pill.css'; 10 | @import './spinner.css'; 11 | @import './tooltip.css'; 12 | -------------------------------------------------------------------------------- /src/elements/layout/row/row.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, BreakpointProps } from '~/models'; 2 | 3 | export interface RowProps extends BreakpointProps<'row' | 'column' | 'row-reverse' | 'column-reverse'>, BaseProps { 4 | centered?: boolean; 5 | } 6 | 7 | export interface RowState extends BaseState { 8 | classes: { base: string }; 9 | } 10 | -------------------------------------------------------------------------------- /src/elements/components/spinner/spinner.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, Dynamic, Variant } from '~/models'; 2 | 3 | export interface SpinnerProps extends BaseProps { 4 | variant?: Dynamic; 5 | full?: boolean; 6 | fullscreen?: boolean; 7 | } 8 | 9 | export interface SpinnerState extends BaseState { 10 | classes: { base: string }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/rollup.config.js: -------------------------------------------------------------------------------- 1 | import config from '../../rollup.config.js'; 2 | import packageJson from './package.json' assert { type: 'json' }; 3 | 4 | export default config({ 5 | dir: './packages/react', 6 | packageJson, 7 | babelPresets: ['@babel/preset-react'], 8 | compilerOptions: { 9 | jsx: 'react', 10 | jsxImportSource: null 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /src/elements/components/pill/pill.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, Dynamic, Intent, Variant } from '~/models'; 2 | 3 | export interface PillProps extends BaseProps { 4 | variant?: Dynamic; 5 | intent?: Dynamic; 6 | disabled?: boolean; 7 | } 8 | 9 | export interface PillState extends BaseState { 10 | classes: { base: string }; 11 | } 12 | -------------------------------------------------------------------------------- /src/elements/layout/container/container.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-container { 4 | width: 100%; 5 | max-width: var(--pa-grid-max-width); 6 | 7 | &--centered { 8 | display: flex; 9 | justify-content: center; 10 | align-items: center; 11 | align-content: center; 12 | } 13 | 14 | &--fluid { 15 | max-width: 100%; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/vue/rollup.config.js: -------------------------------------------------------------------------------- 1 | import vue from 'rollup-plugin-vue'; 2 | import config from '../../rollup.config.js'; 3 | import packageJson from './package.json' assert { type: 'json' }; 4 | 5 | export default config({ 6 | dir: './packages/vue', 7 | packageJson, 8 | postPlugins: [vue({ template: { optimizeSSR: true } })], 9 | external: ['vue'], 10 | dts: false 11 | }); 12 | -------------------------------------------------------------------------------- /src/elements/components/button/button.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, Dynamic, Intent, Variant } from '~/models'; 2 | 3 | export interface ButtonProps extends BaseProps { 4 | variant?: Dynamic; 5 | intent?: Dynamic; 6 | outline?: boolean; 7 | disabled?: boolean; 8 | } 9 | 10 | export interface ButtonState extends BaseState { 11 | classes: { base: string }; 12 | } 13 | -------------------------------------------------------------------------------- /src/elements/layout/column/column.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, BreakpointProps } from '~/models'; 2 | 3 | export interface ColumnProps 4 | extends BreakpointProps<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'content' | 'fill' | 'hide'>, 5 | BaseProps { 6 | centered?: boolean; 7 | } 8 | 9 | export interface ColumnState extends BaseState { 10 | classes: { base: string }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/solid/rollup.config.js: -------------------------------------------------------------------------------- 1 | import withSolid from 'rollup-preset-solid'; 2 | import config from '../../rollup.config.js'; 3 | import packageJson from './package.json' assert { type: 'json' }; 4 | 5 | export default withSolid( 6 | await config({ 7 | dir: './packages/solid', 8 | packageJson, 9 | compilerOptions: { 10 | jsx: 'preserve', 11 | jsxImportSource: 'solid-js' 12 | } 13 | }) 14 | ); 15 | -------------------------------------------------------------------------------- /packages/svelte/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "rootDirs": [ 6 | ".", 7 | ], 8 | "importsNotUsedAsValues": "preserve", 9 | "preserveValueImports": false 10 | }, 11 | "include": [ 12 | "./src/**/*.ts", 13 | "./src/**/*.svelte", 14 | ], 15 | "exclude": [ 16 | "../../node_modules/**" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/preact/rollup.config.js: -------------------------------------------------------------------------------- 1 | import config from '../../rollup.config.js'; 2 | import packageJson from './package.json' assert { type: 'json' }; 3 | 4 | export default config({ 5 | dir: './packages/preact', 6 | packageJson, 7 | babelPresets: ['@babel/preset-react'], 8 | babelPlugins: ['@babel/plugin-transform-react-jsx'], 9 | compilerOptions: { 10 | jsx: 'react', 11 | jsxImportSource: null 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /src/elements/components/breadcrumb/breadcrumb.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, debug } from '~/helpers'; 2 | 3 | class BreadcrumbService { 4 | public getClasses(className: string) { 5 | const base = classesToString(['pa-breadcrumb', className || '']); 6 | 7 | debug(`BreadcrumbService getClasses: base: ${base}`); 8 | return { base }; 9 | } 10 | } 11 | 12 | export const breadcrumbService = new BreadcrumbService(); 13 | -------------------------------------------------------------------------------- /src/models/component.model.ts: -------------------------------------------------------------------------------- 1 | export type Children = any; // TODO 2 | 3 | export type CSS = Partial & { 4 | [key: string]: Partial | string; 5 | }; 6 | 7 | export interface BaseProps { 8 | className?: string; 9 | class?: string; // Fallback className 10 | classList?: string; // Fallback class 11 | children?: Children; 12 | } 13 | 14 | export interface BaseState { 15 | loaded?: boolean; 16 | } 17 | -------------------------------------------------------------------------------- /src/elements/components/breadcrumb/breadcrumb.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState } from '~/models'; 2 | 3 | export interface BreadcrumbItem { 4 | label: string; 5 | href?: string; 6 | } 7 | 8 | export interface BreadcrumbProps extends BaseProps { 9 | items: BreadcrumbItem[]; 10 | separator?: string; 11 | } 12 | 13 | export interface BreadcrumbState extends BaseState { 14 | classes: { base: string }; 15 | separator: string; 16 | } 17 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './codesandbox-angular.helper'; 2 | export * from './codesandbox-preact.helper'; 3 | export * from './codesandbox-qwik.helper'; 4 | export * from './codesandbox-react.helper'; 5 | export * from './codesandbox-solid.helper'; 6 | export * from './codesandbox-svelte.helper'; 7 | export * from './codesandbox-vue.helper'; 8 | export * from './codesandbox-web.helper'; 9 | export * from './codesandbox.helper'; 10 | -------------------------------------------------------------------------------- /src/elements/components/button/button.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-button { 4 | -moz-user-select: none; 5 | -ms-user-select: none; 6 | -webkit-user-select: none; 7 | background-image: none; 8 | cursor: pointer; 9 | display: inline-block; 10 | padding: 0.4rem 1rem; 11 | text-align: center; 12 | touch-action: manipulation; 13 | user-select: none; 14 | 15 | &.is-disabled { 16 | pointer-events: none; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/qwik/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { qwikVite } from '@builder.io/qwik/optimizer'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig(() => { 5 | return { 6 | build: { 7 | target: 'es2020', 8 | lib: { 9 | entry: './src/index.ts', 10 | formats: ['es', 'cjs'], 11 | fileName: (format) => `index.qwik.${format === 'es' ? 'mjs' : 'cjs'}` 12 | } 13 | }, 14 | plugins: [qwikVite()] 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /src/elements/components/breadcrumb/breadcrumb.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-breadcrumb { 4 | display: block; 5 | } 6 | 7 | .pa-breadcrumb__list { 8 | list-style: none; 9 | display: flex; 10 | margin: 0; 11 | padding: 0; 12 | } 13 | 14 | .pa-breadcrumb__item { 15 | display: flex; 16 | align-items: center; 17 | } 18 | 19 | .pa-breadcrumb__link { 20 | text-decoration: none; 21 | } 22 | 23 | .pa-breadcrumb__separator { 24 | margin: 0 0.5rem; 25 | } 26 | -------------------------------------------------------------------------------- /src/elements/enterprise/itchio/itchio.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-itchio { 4 | &__container { 5 | display: flex; 6 | flex-direction: row; 7 | } 8 | 9 | &__image { 10 | width: 100%; 11 | } 12 | 13 | &__info { 14 | display: flex; 15 | flex-direction: column; 16 | justify-content: space-between; 17 | } 18 | 19 | &__texts { 20 | display: flex; 21 | flex-direction: column; 22 | justify-content: flex-start; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/helpers/classes.helper.ts: -------------------------------------------------------------------------------- 1 | // TODO: Angular problems typing here 2 | export function classesToString(classes: (string | any)[]): string { 3 | let stringWithClasses = ''; 4 | 5 | classes.map((className) => { 6 | if (Array.isArray(className) && className[0]) { 7 | stringWithClasses += ` ${className[1]}`; 8 | } 9 | 10 | if (!Array.isArray(className)) { 11 | stringWithClasses += ` ${className}`; 12 | } 13 | }); 14 | 15 | return stringWithClasses; 16 | } 17 | -------------------------------------------------------------------------------- /src/helpers/arg-type.helper.ts: -------------------------------------------------------------------------------- 1 | import { breakpoints } from '../models'; 2 | 3 | export function getBreakpointArgTypes(description, options) { 4 | const argTypes = {}; 5 | 6 | breakpoints.map((breakpoint) => { 7 | argTypes[breakpoint.value] = { 8 | name: breakpoint.value, 9 | description: description.replace('{breakpoint}', breakpoint.key), 10 | table: {}, 11 | options, 12 | control: { type: 'select' } 13 | }; 14 | }); 15 | 16 | return argTypes; 17 | } 18 | -------------------------------------------------------------------------------- /src/models/breakpoint.model.ts: -------------------------------------------------------------------------------- 1 | export enum Breakpoint { 2 | Basic = 'basic', 3 | XXS = 'xxs', 4 | XS = 'xs', 5 | S = 's', 6 | M = 'm', 7 | L = 'l', 8 | XL = 'xl', 9 | XXL = 'xxl' 10 | } 11 | 12 | export interface BreakpointProps { 13 | basic?: T; 14 | xxs?: T; 15 | xs?: T; 16 | s?: T; 17 | m?: T; 18 | l?: T; 19 | xl?: T; 20 | xxl?: T; 21 | } 22 | 23 | export const breakpoints = Object.entries(Breakpoint).map(([key, value]: [string, string]) => ({ key, value })); 24 | -------------------------------------------------------------------------------- /src/elements/components/avatar/avatar.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, CSS, Dynamic, Variant } from '~/models'; 2 | 3 | export interface AvatarProps extends BaseProps { 4 | variant?: Dynamic; 5 | name?: string; 6 | unavatar?: string; 7 | url?: string; 8 | disabled?: boolean; 9 | } 10 | 11 | export interface AvatarState extends BaseState { 12 | classes: { base: string; container: string }; 13 | styles: { container: CSS }; 14 | initials: string; 15 | source: string; 16 | } 17 | -------------------------------------------------------------------------------- /src/elements/layout/container/container.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString } from '~/helpers'; 2 | 3 | class ContainerService { 4 | public getClasses(centered: boolean, fluid: boolean, className: string) { 5 | const base = classesToString([ 6 | 'pa-container', 7 | [centered, `pa-column--centered`], 8 | [fluid, 'pa-container--fluid'], 9 | className || '' 10 | ]); 11 | 12 | return { base }; 13 | } 14 | } 15 | 16 | export const containerService = new ContainerService(); 17 | -------------------------------------------------------------------------------- /src/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './arg-type.helper'; 2 | export * from './breakpoint.helper'; 3 | export * from './classes.helper'; 4 | export * from './code.helper'; 5 | export * from './codejar.helper'; 6 | export * from './color.helper'; 7 | export * from './debug.helper'; 8 | export * from './element.helper'; 9 | export * from './inject-script.helper'; 10 | export * from './itchio.helper'; 11 | export * from './object.helper'; 12 | export * from './platform.helper'; 13 | export * from './version.helper'; 14 | export * from './wait.helper'; 15 | -------------------------------------------------------------------------------- /src/elements/components/avatar/avatar.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-avatar { 4 | display: inline-flex; 5 | 6 | &__container { 7 | background-color: var(--pa-avatar-background); 8 | color: var(--pa-avatar-foreground); 9 | display: inline-flex; 10 | justify-content: center; 11 | align-items: center; 12 | } 13 | 14 | &.is-disabled { 15 | pointer-events: none; 16 | opacity: 0.5; 17 | } 18 | 19 | &__image { 20 | object-fit: cover; 21 | max-width: 100%; 22 | max-height: 100%; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/solid/copy-css.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra'; 2 | import glob from 'glob'; 3 | import path from 'path'; 4 | 5 | const cssFiles = glob.sync(`./src/**/*.css`); 6 | cssFiles.forEach((fileName) => { 7 | const file = path.parse(fileName); 8 | 9 | fs.copySync(fileName, `./dist/index${file.dir.replace('src', '')}/${file.base}`); 10 | }); 11 | 12 | const themesFiles = glob.sync(`../../.themes/**.css`); 13 | themesFiles.forEach((fileName) => { 14 | const file = path.parse(fileName); 15 | 16 | fs.copySync(fileName, `./dist/themes/${file.base}`); 17 | }); 18 | -------------------------------------------------------------------------------- /.storybook/theme.js: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming'; 2 | 3 | export const Themes = { 4 | manager: create({ 5 | base: 'light', 6 | brandTitle: 'Papanasi - Universal UI Library', 7 | brandUrl: 'https://github.com/ckgrafico/papanasi', 8 | brandImage: 'https://raw.githubusercontent.com/CKGrafico/papanasi/main/docs/resources/logo-github.svg', 9 | colorSecondary: '#ad99ff', 10 | fontBase: '"Source Sans Pro", sans-serif' 11 | }), 12 | docs: create({ 13 | base: 'light', 14 | fontBase: '"Source Sans Pro", sans-serif' 15 | }) 16 | }; 17 | -------------------------------------------------------------------------------- /src/elements/components/pill/pill.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, debug } from '~/helpers'; 2 | 3 | class PillService { 4 | public getClasses(variant: string, intent: string, disabled: boolean, className: string) { 5 | const base = classesToString([ 6 | 'pa-pill', 7 | [variant, `pa-pill--${variant}`], 8 | [intent, `is-${intent}`], 9 | [disabled, 'is-disabled'], 10 | className || '' 11 | ]); 12 | 13 | debug(`PillService getClasses: base: ${base}`); 14 | return { base }; 15 | } 16 | } 17 | 18 | export const pillService = new PillService(); 19 | -------------------------------------------------------------------------------- /src/helpers/debug.helper.ts: -------------------------------------------------------------------------------- 1 | export enum DebugLevel { 2 | None = 0, 3 | Log = 1, 4 | Breakpoint = 2 5 | } 6 | 7 | let debugLevel = DebugLevel.None; 8 | 9 | const debugStrategies = { 10 | [DebugLevel.None]: () => null, 11 | [DebugLevel.Log]: (message: string) => console.log(message), 12 | [DebugLevel.Breakpoint]: (message: string) => { 13 | console.log(message); 14 | debugger; 15 | } 16 | }; 17 | 18 | export function setDebugLevel(level: DebugLevel) { 19 | debugLevel = level; 20 | } 21 | 22 | export function debug(message: string) { 23 | debugStrategies[debugLevel](message); 24 | } 25 | -------------------------------------------------------------------------------- /src/helpers/platform.helper.ts: -------------------------------------------------------------------------------- 1 | import { debug } from './debug.helper'; 2 | 3 | export enum Platform { 4 | Default = 'default', 5 | Angular = 'angular', 6 | Preact = 'preact', 7 | Qwik = 'qwik', 8 | React = 'react', 9 | Solid = 'solid', 10 | Svelte = 'svelte', 11 | Vue = 'vue', 12 | Webcomponents = 'webcomponents' 13 | } 14 | 15 | let platform = Platform.Default; 16 | 17 | export function setPlatform(newPlatform: Platform) { 18 | debug(`Setting new platform ${newPlatform}`); 19 | 20 | platform = newPlatform; 21 | } 22 | 23 | export function getPlatform(): Platform { 24 | return platform; 25 | } 26 | -------------------------------------------------------------------------------- /src/elements/layout/row/row.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-row { 4 | display: flex; 5 | flex-wrap: wrap; 6 | 7 | margin-bottom: calc(-1 * var(--pa-grid-gutter-vertical)); 8 | margin-left: calc(-1 * var(--pa-grid-gutter-horizontal)); 9 | margin-right: calc(-1 * var(--pa-grid-gutter-horizontal)); 10 | margin-top: calc(-1 * var(--pa-grid-gutter-vertical)); 11 | 12 | @each $breakpoint in var(--internal-breakpoints) { 13 | @each $value in var(--internal-flex-directions) { 14 | @mixin breakpoint-modifier $breakpoint, $value { 15 | flex-direction: $value; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/elements/layout/row/row.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, getBreakpointClasses } from '~/helpers'; 2 | 3 | class RowService { 4 | public getClasses( 5 | basic: string, 6 | xxs: string, 7 | xs: string, 8 | s: string, 9 | m: string, 10 | l: string, 11 | xl: string, 12 | xxl: string, 13 | className: string 14 | ) { 15 | const base = classesToString([ 16 | 'pa-row', 17 | getBreakpointClasses(basic, xxs, xs, s, m, l, xl, xxl, 'pa-row--'), 18 | className || '' 19 | ]); 20 | 21 | return { base }; 22 | } 23 | } 24 | 25 | export const rowService = new RowService(); 26 | -------------------------------------------------------------------------------- /src/elements/components/pill/pill.lite.tsx: -------------------------------------------------------------------------------- 1 | import { useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './pill.css'; 3 | import type { PillProps, PillState } from './pill.model'; 4 | import { pillService } from './pill.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Pill(props: PillProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return pillService.getClasses(props.variant, props.intent, props.disabled, props.className || props.classList); 12 | } 13 | }); 14 | 15 | return {props.children}; 16 | } 17 | -------------------------------------------------------------------------------- /src/elements/components/spinner/spinner.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, debug } from '~/helpers'; 2 | 3 | class SpinnerService { 4 | public getClasses(variant: string, full: boolean, fullscreen: boolean, className: string) { 5 | const base = classesToString([ 6 | 'pa-spinner', 7 | [variant, `pa-spinner--${variant}`], 8 | [full && !fullscreen, 'pa-spinner--full'], 9 | [fullscreen, 'pa-spinner--fullscreen'], 10 | className || '' 11 | ]); 12 | 13 | debug(`SpinnerService getClasses: base: ${base}`); 14 | return { base }; 15 | } 16 | } 17 | 18 | export const spinnerService = new SpinnerService(); 19 | -------------------------------------------------------------------------------- /src/elements/components/button/button.lite.tsx: -------------------------------------------------------------------------------- 1 | import { useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './button.css'; 3 | import type { ButtonProps, ButtonState } from './button.model'; 4 | import { buttonService } from './button.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Button(props: ButtonProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return buttonService.getClasses(props.variant, props.outline, props.intent, props.disabled, props.className); 12 | } 13 | }); 14 | 15 | return ; 16 | } 17 | -------------------------------------------------------------------------------- /src/elements/components/button/button.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, debug } from '~/helpers'; 2 | 3 | class ButtonService { 4 | public getClasses(variant: string, outline: boolean, intent: string, disabled: boolean, className: string) { 5 | const base = classesToString([ 6 | 'pa-button', 7 | [variant, `pa-button--${variant}`], 8 | [outline, 'pa-button--outline'], 9 | [intent, `is-${intent}`], 10 | [disabled, 'is-disabled'], 11 | className || '' 12 | ]); 13 | 14 | debug(`ButtonService getClasses: base: ${base}`); 15 | return { base }; 16 | } 17 | } 18 | 19 | export const buttonService = new ButtonService(); 20 | -------------------------------------------------------------------------------- /packages/qwik/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "target": "ES2017", 5 | "module": "ES2020", 6 | "lib": [ 7 | "es2020", 8 | "DOM" 9 | ], 10 | "jsx": "react-jsx", 11 | "jsxImportSource": "@builder.io/qwik", 12 | "strict": false, 13 | "declaration": true, 14 | "declarationDir": "types", 15 | "resolveJsonModule": true, 16 | "moduleResolution": "node", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true, 19 | "incremental": true, 20 | "isolatedModules": true, 21 | "types": [ 22 | "vite/client" 23 | ] 24 | }, 25 | "include": [ 26 | "src" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState } from '~/models'; 2 | 3 | export interface ToastProps extends BaseProps { 4 | disabled?: boolean; 5 | } 6 | 7 | export interface ToastState extends BaseState { 8 | classes: { base: string }; 9 | toasts: ToastPayload[]; 10 | toastSubscription: { 11 | unsubscribe(): void; 12 | }; 13 | } 14 | 15 | export type ToastPayload = { 16 | id?: string; 17 | message: string; 18 | }; 19 | 20 | // TODO Move to generic 21 | export type ToastChannelEvent = { 22 | channel: string; 23 | payload: T | undefined; 24 | }; 25 | 26 | export type ToastCallback = (event: ToastChannelEvent) => void; 27 | -------------------------------------------------------------------------------- /src/elements/layout/container/container.lite.tsx: -------------------------------------------------------------------------------- 1 | import { useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './container.css'; 3 | import type { ContainerProps, ContainerState } from './container.model'; 4 | import { containerService } from './container.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Container(props: ContainerProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return containerService.getClasses(props.centered || false, props.fluid, props.className || props.classList); 12 | } 13 | }); 14 | 15 | return
{props.children}
; 16 | } 17 | -------------------------------------------------------------------------------- /hooks/post-package.hook.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra'; 2 | import glob from 'glob'; 3 | import lernaJson from '../lerna.json' assert { type: 'json' }; 4 | const version = lernaJson.version; 5 | const filesToReplace = glob.sync(`./packages/**/{,!node_modules)/**/}*.{js,ts,map,cjs,mjs}`); 6 | 7 | function setCorrrectVersion(file) { 8 | if (file.includes('node_modules')) { 9 | return; 10 | } 11 | 12 | const data = fs.readFileSync(file, 'utf8'); 13 | const result = data.replace(/setVersion\((\'|\")(.*)(\'|\")\);/g, `setVersion($3${version}$3);`); 14 | 15 | fs.writeFileSync(file, result, 'utf8'); 16 | } 17 | 18 | filesToReplace.forEach((file) => { 19 | setCorrrectVersion(file); 20 | }); 21 | -------------------------------------------------------------------------------- /src/elements/enterprise/itchio/itchio.model.ts: -------------------------------------------------------------------------------- 1 | import type { BaseProps, BaseState, Children } from '~/models'; 2 | 3 | export type ItchioGameInfo = { 4 | title: string; 5 | cover_image: string; 6 | price: string; 7 | }; 8 | 9 | export interface ItchioProps extends BaseProps { 10 | user: string; 11 | game: string; 12 | width?: number; 13 | height?: number; 14 | onLoad?: (info: ItchioGameInfo) => void; 15 | secret?: string; 16 | slotLoading?: Children; 17 | } 18 | 19 | export interface ItchioState extends BaseState { 20 | classes: { base: string }; 21 | gameInfo: ItchioGameInfo; 22 | onClickAction: (user: string, game: string, width: number, height: number) => void; 23 | } 24 | -------------------------------------------------------------------------------- /src/helpers/wait.helper.ts: -------------------------------------------------------------------------------- 1 | export function wait(ms = 10): Promise { 2 | return new Promise((resolve) => setTimeout(resolve, ms)); 3 | } 4 | 5 | export function waitUntilTrue(condition: () => boolean, maxTime = 1000): Promise { 6 | const startTime = performance.now(); 7 | 8 | return new Promise((resolve) => { 9 | const loop = () => { 10 | const now = performance.now(); 11 | 12 | if (now - startTime > maxTime) { 13 | throw new Error('Maximum time waiting for be true'); 14 | } 15 | 16 | if (condition()) { 17 | resolve(); 18 | } else { 19 | requestAnimationFrame(loop); 20 | } 21 | }; 22 | 23 | loop(); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /compiler/platforms/solid.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import compiler from '../base.compiler.js'; 3 | 4 | const DEFAULT_OPTIONS = { 5 | target: 'solid', 6 | extension: 'tsx', 7 | state: 'useState', 8 | styles: 'styled-components' 9 | }; 10 | 11 | (async () => { 12 | function customReplace(props) { 13 | const { outFile } = props; 14 | 15 | const data = fs.readFileSync(outFile, 'utf8'); 16 | const result = data 17 | // fix keys 18 | .replace(/ key\=/g, ' data-key=') 19 | // Replace classname for class 20 | .replace(/\.className/g, '.class'); 21 | fs.writeFileSync(outFile, result, 'utf8'); 22 | } 23 | 24 | await compiler.compile({ ...DEFAULT_OPTIONS, customReplace }); 25 | })(); 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/component-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Component request 3 | about: Suggest a component 4 | title: 'Add the _________ component' 5 | labels: 'Component' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your component 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 some examples of this component** 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 | -------------------------------------------------------------------------------- /src/helpers/code.helper.ts: -------------------------------------------------------------------------------- 1 | import cssLanguage from 'highlight.js/lib/languages/css'; 2 | import jsLanguage from 'highlight.js/lib/languages/javascript'; 3 | import markdownLanguage from 'highlight.js/lib/languages/markdown'; 4 | import tsLanguage from 'highlight.js/lib/languages/typescript'; 5 | import xmlLanguage from 'highlight.js/lib/languages/xml'; 6 | 7 | export const codeLanguages = { 8 | javascript: jsLanguage, 9 | typescript: tsLanguage, 10 | css: cssLanguage, 11 | xml: xmlLanguage, 12 | markdown: markdownLanguage 13 | }; 14 | 15 | export const injectCodeCore = async () => (await import('highlight.js/lib/core')).default; 16 | 17 | export function addCodeLanguage(name: string, language) { 18 | codeLanguages[name] = language; 19 | } 20 | -------------------------------------------------------------------------------- /src/elements/layout/row/row.lite.tsx: -------------------------------------------------------------------------------- 1 | import { useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './row.css'; 3 | import type { RowProps, RowState } from './row.model'; 4 | import { rowService } from './row.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Row(props: RowProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return rowService.getClasses( 12 | props.basic, 13 | props.xxs, 14 | props.xs, 15 | props.s, 16 | props.m, 17 | props.l, 18 | props.xl, 19 | props.xxl, 20 | props.className 21 | ); 22 | } 23 | }); 24 | 25 | return
{props.children}
; 26 | } 27 | -------------------------------------------------------------------------------- /src/helpers/itchio.helper.ts: -------------------------------------------------------------------------------- 1 | // from https://static.itch.io/api.js 2 | export const Itch: any = {}; 3 | import { ofetch } from 'ofetch'; 4 | 5 | Itch.getGameData = async function (opts) { 6 | if (opts == null) { 7 | opts = {}; 8 | } 9 | const domain = opts.domain || 'itch.io'; 10 | if (!opts.user) { 11 | throw new Error('Missing user'); 12 | } 13 | if (!opts.game) { 14 | throw new Error('Missing game'); 15 | } 16 | let url = 'https://' + opts.user + '.' + domain + '/' + opts.game + '/data.json'; 17 | if (opts.secret) { 18 | url = url + '?secret=' + opts.secret; 19 | } 20 | 21 | const game = await ofetch(url, { parseResponse: JSON.parse }); 22 | 23 | return typeof opts.onComplete === 'function' ? opts.onComplete(game) : void 0; 24 | }; 25 | -------------------------------------------------------------------------------- /src/elements/layout/column/column.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, getBreakpointClasses } from '~/helpers'; 2 | 3 | class ColumnService { 4 | public getClasses( 5 | centered: boolean, 6 | basic: number | string, 7 | xxs: number | string, 8 | xs: number | string, 9 | s: number | string, 10 | m: number | string, 11 | l: number | string, 12 | xl: number | string, 13 | xxl: number | string, 14 | className: string 15 | ) { 16 | const base = classesToString([ 17 | 'pa-column', 18 | [centered, `pa-column--centered`], 19 | getBreakpointClasses(basic, xxs, xs, s, m, l, xl, xxl, 'pa-column--'), 20 | className || '' 21 | ]); 22 | 23 | return { base }; 24 | } 25 | } 26 | 27 | export const columnService = new ColumnService(); 28 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.bus.ts: -------------------------------------------------------------------------------- 1 | import { EventBus } from '@trutoo/event-bus'; 2 | import { ToastCallback, ToastPayload } from './toast.model'; 3 | 4 | const BUS_NAME = 'toast'; 5 | const bus = new EventBus(); 6 | const state: ToastPayload[] = []; 7 | 8 | // TODO: If more buses in the future, move to generic 9 | const subscribe = (callback: ToastCallback) => bus.subscribe(BUS_NAME, callback); 10 | const register = (optionsType = { type: Object }) => bus.register(BUS_NAME, optionsType); 11 | const publish = (payload: ToastPayload) => { 12 | state.push(payload); 13 | bus.publish(BUS_NAME, payload); 14 | }; 15 | 16 | // TODO: Can i move all the logic to the service?? 17 | 18 | export const toastBus = { 19 | subscribe, 20 | register, 21 | publish, 22 | state: () => state 23 | }; 24 | -------------------------------------------------------------------------------- /rollup.themes.config.js: -------------------------------------------------------------------------------- 1 | import postcss from 'rollup-plugin-postcss'; 2 | 3 | import commandLineArgs from 'command-line-args'; 4 | 5 | const optionDefinitions = [ 6 | { name: 'config', alias: 'c', type: String }, 7 | { name: 'theme', alias: 't', type: String } 8 | ]; 9 | 10 | export default () => { 11 | const cliConfig = commandLineArgs(optionDefinitions); 12 | const postcssConfig = require(path.resolve(__dirname, './postcss.config.cjs')); 13 | 14 | return [ 15 | { 16 | input: `./src/styles/themes/${cliConfig.theme}/index.css`, 17 | output: [ 18 | { 19 | file: `.themes/${cliConfig.theme}.css`, 20 | sourcemap: 'inline' 21 | } 22 | ], 23 | plugins: [postcss({ ...postcssConfig, inject: false, extract: `${cliConfig.theme}.css` })] 24 | } 25 | ]; 26 | }; 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ES5", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": false, 8 | "skipLibCheck": true, 9 | "jsx": "preserve", 10 | "jsxImportSource": "@builder.io/mitosis", 11 | "module": "ESNext", 12 | "declaration": true, 13 | "sourceMap": true, 14 | "moduleResolution": "node", 15 | "allowSyntheticDefaultImports": true, 16 | "experimentalDecorators": true, 17 | "resolveJsonModule": true, 18 | "importsNotUsedAsValues": "preserve", 19 | "paths": { 20 | "~/helpers/*": [ 21 | "./src/helpers/*" 22 | ], 23 | "~/models/*": [ 24 | "./src/models/*" 25 | ], 26 | "~/*": [ 27 | "./src/*" 28 | ] 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /compiler/themes.tasks.js: -------------------------------------------------------------------------------- 1 | import { Listr } from 'listr2'; 2 | 3 | (async () => { 4 | const execa = (await import('execa')).command; 5 | const themes = ['papanasi', 'sketch']; 6 | 7 | const tasks = new Listr([ 8 | { 9 | title: `Compile Themes: ${themes.join(', ')}`, 10 | task: () => { 11 | return new Listr( 12 | themes.map((theme) => ({ 13 | title: `Generate ${theme} theme`, 14 | task: () => 15 | execa(`rollup -c rollup.themes.config.js --theme ${theme}`).catch(() => { 16 | throw new Error(`Cannot generate the theme ${theme}`); 17 | }) 18 | })), 19 | { concurrent: true } 20 | ); 21 | } 22 | } 23 | ]); 24 | 25 | tasks.run().catch((err) => { 26 | console.error(err); 27 | }); 28 | })(); 29 | -------------------------------------------------------------------------------- /src/elements/layout/column/column.lite.tsx: -------------------------------------------------------------------------------- 1 | import { useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './column.css'; 3 | import type { ColumnProps, ColumnState } from './column.model'; 4 | import { columnService } from './column.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Column(props: ColumnProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return columnService.getClasses( 12 | props.centered || false, 13 | props.basic, 14 | props.xxs, 15 | props.xs, 16 | props.s, 17 | props.m, 18 | props.l, 19 | props.xl, 20 | props.xxl, 21 | props.className 22 | ); 23 | } 24 | }); 25 | 26 | return
{props.children}
; 27 | } 28 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-at-rules-variables')({ 4 | atRules: ['each', 'mixin', 'custom-media'], 5 | variables: { 6 | ['--internal-columns']: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].join(', '), 7 | ['--internal-columns-total']: '12', 8 | ['--internal-breakpoints']: ['basic', 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl'].join(', '), 9 | ['--internal-flex-directions']: ['row', 'column', 'row-reverse', 'column-reverse'].join(', ') 10 | } 11 | }), 12 | require('postcss-import'), 13 | require('postcss-calc')({ preserve: false }), 14 | require('postcss-each'), 15 | require('postcss-nested'), 16 | require('postcss-mixins'), 17 | require('autoprefixer'), 18 | require('postcss-discard-comments') 19 | ], 20 | inject: true 21 | }; 22 | -------------------------------------------------------------------------------- /src/helpers/element.helper.ts: -------------------------------------------------------------------------------- 1 | export function querySelectorAllObservable( 2 | element: HTMLElement, 3 | selector: string, 4 | callback: (element: HTMLElement) => void 5 | ) { 6 | if (!element.querySelectorAll) { 7 | return; 8 | } 9 | 10 | const elements = Array.from(element.querySelectorAll(selector)); 11 | 12 | if (callback) { 13 | elements.forEach(callback); 14 | } 15 | 16 | const observer = new MutationObserver((mutations) => { 17 | mutations.forEach((mutation) => { 18 | mutation.addedNodes.forEach((element: HTMLElement) => { 19 | if (element.nodeType === Node.ELEMENT_NODE && element.matches(selector)) { 20 | elements.push(element); 21 | callback && callback(element); 22 | } 23 | }); 24 | }); 25 | }); 26 | 27 | observer.observe(element, { childList: true, subtree: true }); 28 | 29 | return elements; 30 | } 31 | -------------------------------------------------------------------------------- /src/elements/components/spinner/spinner.lite.tsx: -------------------------------------------------------------------------------- 1 | import { useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './spinner.css'; 3 | import type { SpinnerProps, SpinnerState } from './spinner.model'; 4 | import { spinnerService } from './spinner.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | export default function Spinner(props: SpinnerProps) { 8 | const state = useStore({ 9 | loaded: false, 10 | get classes() { 11 | return spinnerService.getClasses(props.variant, props.full, props.fullscreen, props.className || props.classList); 12 | } 13 | }); 14 | 15 | return ( 16 |
17 | 18 | 19 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/elements/components/code/code.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-code { 4 | --pa-code-padding: 1rem; 5 | 6 | display: block; 7 | margin-bottom: 1rem; 8 | min-height: 5rem; 9 | position: relative; 10 | width: 100%; 11 | 12 | &__editor.hljs { 13 | margin: 0; 14 | padding-bottom: 0; 15 | padding-top: 0; 16 | } 17 | 18 | &__actions { 19 | position: absolute; 20 | bottom: 0; 21 | right: 0; 22 | max-width: 100%; 23 | display: flex; 24 | z-index: 10; 25 | } 26 | 27 | &__action { 28 | display: flex; 29 | padding: 0.35rem; 30 | 31 | &--copy { 32 | cursor: pointer; 33 | } 34 | } 35 | 36 | &__link { 37 | display: inline-flex; 38 | align-items: center; 39 | } 40 | 41 | &__icon { 42 | width: 0.75rem; 43 | margin-right: 0.25rem; 44 | } 45 | 46 | &__link--text &__icon { 47 | margin-right: 0; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/helpers/inject-script.helper.ts: -------------------------------------------------------------------------------- 1 | // From: https://stackoverflow.com/questions/13121948/dynamically-add-script-tag-with-src-that-may-include-document-write 2 | 3 | import { getDocument } from 'ssr-window'; 4 | 5 | export function addScript(src, id) { 6 | const identifier = `inject-${id}`; 7 | const document = getDocument(); 8 | 9 | return new Promise((resolve, reject) => { 10 | if (document.querySelector(`#${identifier}`)) { 11 | resolve(''); 12 | return; 13 | } 14 | 15 | const script = document.createElement('script'); 16 | 17 | script.setAttribute('src', src); 18 | script.setAttribute('id', identifier); 19 | script.setAttribute('type', 'text/javascript'); 20 | 21 | if (!script.addEventListener) { 22 | return; 23 | } 24 | 25 | script.addEventListener('load', resolve); 26 | script.addEventListener('error', reject); 27 | document.body.appendChild(script); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /compiler/platforms/react.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import compiler from '../base.compiler.js'; 3 | 4 | const DEFAULT_OPTIONS = { 5 | target: 'react', 6 | extension: 'tsx', 7 | state: 'useState', 8 | styles: 'style-tag' 9 | }; 10 | 11 | (async () => { 12 | function customReplace(props) { 13 | const { outFile, name, pascalName } = props; 14 | 15 | const data = fs.readFileSync(outFile, 'utf8'); 16 | const result = data 17 | // Import types 18 | .replace(/import/, `import type { ${pascalName}Props } from './${name}.model';\nimport`) 19 | // fix props on qwik 20 | .replace(/\(props\) ?\{/g, `(props: ${pascalName}Props) {`) 21 | // fix contenteditable 22 | .replace(/contentEditable\=(.*)/g, 'contentEditable=$1\nsuppressContentEditableWarning={true}'); 23 | fs.writeFileSync(outFile, result, 'utf8'); 24 | } 25 | 26 | await compiler.compile({ ...DEFAULT_OPTIONS, customReplace }); 27 | })(); 28 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/tooltip.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-tooltip { 4 | --pa-tooltip-background: var(--pa-color-basic-darkest); 5 | --pa-tooltip-color: var(--pa-color-basic-brightest); 6 | --pa-tooltip-distance: 0.5rem; 7 | --pa-tooltip-font-size: var(--pa-font-size-small); 8 | --pa-tooltip-padding: 0.25rem; 9 | --pa-tooltip-radius: 0.25rem; 10 | --pa-tooltip-transition-time: var(--pa-transition-duration-fast); 11 | 12 | @mixin shared-styles; 13 | 14 | background-color: var(--pa-tooltip-background); 15 | border-radius: var(--pa-tooltip-radius); 16 | color: var(--pa-tooltip-color); 17 | font-family: var(--pa-font-family); 18 | font-size: var(--pa-tooltip-font-size); 19 | padding: var(--pa-tooltip-padding); 20 | transition: var(--pa-transition-opacity) var(--pa-tooltip-transition-time); 21 | transform: translateY(var(--pa-tooltip-distance)); 22 | 23 | &.is-hidden { 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/tooltip.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-tooltip { 4 | --pa-tooltip-background: var(--pa-color-basic-darkest); 5 | --pa-tooltip-color: var(--pa-color-basic-brightest); 6 | --pa-tooltip-distance: 0.5rem; 7 | --pa-tooltip-font-size: var(--pa-font-size-small); 8 | --pa-tooltip-padding: 0.25rem; 9 | --pa-tooltip-radius: 0.25rem; 10 | --pa-tooltip-transition-time: var(--pa-transition-duration-fast); 11 | 12 | @mixin shared-styles; 13 | 14 | background-color: var(--pa-tooltip-background); 15 | border-radius: var(--pa-tooltip-radius); 16 | color: var(--pa-tooltip-color); 17 | font-family: var(--pa-font-family); 18 | font-size: var(--pa-tooltip-font-size); 19 | padding: var(--pa-tooltip-padding); 20 | transition: var(--pa-transition-opacity) var(--pa-tooltip-transition-time); 21 | transform: translateY(var(--pa-tooltip-distance)); 22 | 23 | &.is-hidden { 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-prettier/recommended", 3 | "ignoreFiles": [ 4 | "**/*.html", 5 | "**/*.js", 6 | "**/*.ts" 7 | ], 8 | "plugins": [ 9 | "stylelint-prettier", 10 | ], 11 | "rules": { 12 | "prettier/prettier": true, 13 | "at-rule-no-unknown": null, 14 | "font-family-no-missing-generic-family-keyword": null, 15 | "no-empty-source": null, 16 | "shorthand-property-no-redundant-values": null, 17 | "block-no-empty": null, 18 | "no-duplicate-selectors": true, 19 | "color-hex-length": "long", 20 | "color-named": "never", 21 | "selector-no-qualifying-type": true, 22 | "selector-attribute-quotes": "always", 23 | "property-no-vendor-prefix": true, 24 | "value-no-vendor-prefix": true, 25 | "at-rule-no-vendor-prefix": true, 26 | "selector-pseudo-element-colon-notation": "single", 27 | "selector-no-vendor-prefix": true, 28 | "media-feature-name-no-vendor-prefix": true 29 | } 30 | } -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, debug } from '~/helpers'; 2 | import { toastBus } from './toast.bus'; 3 | import { ToastChannelEvent, ToastPayload } from './toast.model'; 4 | 5 | class ToastService { 6 | private toasts: ToastPayload[] = []; 7 | 8 | private onChangeToasts(event: ToastChannelEvent) { 9 | this.toasts = toastBus.state(); 10 | debug(`ToastService onChangeToasts: toasts: ${this.toasts}`); 11 | } 12 | 13 | public getClasses(disabled: boolean, className: string) { 14 | const base = classesToString(['pa-toast', [disabled, 'is-disabled'], className || '']); 15 | 16 | debug(`ToastService getClasses: base: ${base}`); 17 | return { base }; 18 | } 19 | 20 | public getToasts() { 21 | return this.toasts; 22 | } 23 | 24 | public subscribe() { 25 | debug('ToastService subscribe'); 26 | return toastBus.subscribe(this.onChangeToasts); 27 | } 28 | } 29 | 30 | export const toastService = new ToastService(); 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 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 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.storybook/components/customization.css: -------------------------------------------------------------------------------- 1 | .customization { 2 | --pa-grid-gutter-horizontal: 0.35rem; 3 | --pa-grid-gutter-vertical: 0.25rem; 4 | 5 | &__row { 6 | flex-direction: row !important; /* Because Storybook bisc styles... */ 7 | } 8 | 9 | &__label { 10 | font-weight: var(--pa-font-weight-medium); 11 | margin-bottom: 0.75rem; 12 | } 13 | 14 | &__properties { 15 | flex-direction: column !important; /* Because Storybook bisc styles... */ 16 | } 17 | 18 | &__theme, 19 | &__button { 20 | --size: 5rem; 21 | 22 | display: flex; 23 | justify-content: center; 24 | align-items: center; 25 | height: var(--size); 26 | width: var(--size); 27 | max-width: var(--size); 28 | } 29 | 30 | &__button { 31 | --size: 90%; 32 | 33 | background-color: #e6e1fc; /* move to variables */ 34 | border-radius: 1rem; 35 | cursor: pointer; 36 | font-size: 0.75rem; 37 | color: #483f6f; 38 | } 39 | 40 | &__theme.is-selected &__button { 41 | background-color: #ad99ff; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/pill.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-pill { 4 | @mixin shared-styles; 5 | 6 | --pa-pill-radius: 10rem; 7 | --pa-pill-font-weight: var(--pa-font-weight-medium); 8 | 9 | background-color: var(--pa-color-basic-brightest); 10 | border-color: var(--pa-color-basic-bright); 11 | border-radius: var(--pa-pill-radius); 12 | color: var(--pa-color-basic-darker); 13 | font-family: var(--pa-font-family); 14 | font-weight: var(--pa-pill-font-weight); 15 | transition-duration: var(--pa-transition-duration-normal); 16 | transition-property: var(--pa-transition-colors); 17 | 18 | @each $variant in primary, secondary, tertiary { 19 | &--$(variant) { 20 | background-color: var(--pa-color-$(variant)-normal); 21 | border-color: transparent; 22 | color: var(--pa-color-basic-brightest); 23 | } 24 | } 25 | 26 | @each $intent in info, success, warning, error { 27 | &.is-$(intent) { 28 | background-color: var(--pa-color-$(intent)-bright); 29 | color: var(--pa-color-$(intent)-darkest); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/avatar.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-avatar { 4 | --pa-avatar-size: 3rem; 5 | --pa-avatar-padding: 0.5rem; 6 | --pa-avatar-radius: 100%; 7 | --pa-avatar-initials-weight: var(--pa-font-weight-medium); 8 | 9 | @mixin shared-styles; 10 | 11 | &__container { 12 | border-radius: var(--pa-avatar-radius); 13 | box-sizing: border-box; 14 | font-family: var(--pa-font-family); 15 | font-weight: var(--pa-avatar-initials-weight); 16 | height: var(--pa-avatar-size); 17 | padding: var(--pa-avatar-padding); 18 | width: var(--pa-avatar-size); 19 | } 20 | 21 | @each $variant in primary, secondary, tertiary { 22 | &--$(variant) &__container { 23 | --pa-avatar-background: var(--pa-color-$(variant)-normal); 24 | --pa-avatar-foreground: var(--pa-color-basic-brightest); 25 | } 26 | } 27 | 28 | &__image { 29 | border-radius: var(--pa-avatar-radius); 30 | box-sizing: border-box; 31 | max-width: calc(100% + var(--pa-avatar-padding) * 2); 32 | max-height: calc(100% + var(--pa-avatar-padding) * 2); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Quique Fdez Guerra 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. 22 | -------------------------------------------------------------------------------- /src/elements/components/spinner/spinner.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | .pa-spinner { 4 | display: inline-flex; 5 | 6 | --pa-spinner-size: 3rem; 7 | --pa-spinner-stroke: 4; 8 | --pa-spinner-offset: 160; 9 | --pa-spinner-duration: 2s; 10 | 11 | &--full, 12 | &--fullscreen { 13 | align-items: center; 14 | display: flex; 15 | justify-content: center; 16 | height: 100%; 17 | left: 0; 18 | position: absolute; 19 | top: 0; 20 | width: 100%; 21 | } 22 | 23 | &--fullscreen { 24 | height: 100vh; 25 | position: fixed; 26 | width: 100vw; 27 | } 28 | 29 | &__icon { 30 | animation: rotator var(--pa-spinner-duration) linear infinite; 31 | height: var(--pa-spinner-size); 32 | width: var(--pa-spinner-size); 33 | } 34 | 35 | &__path { 36 | stroke: var(--pa-color-basic-normal); 37 | stroke-dasharray: var(--pa-spinner-offset); 38 | stroke-dashoffset: 0; 39 | stroke-width: var(--pa-spinner-stroke); 40 | transform-origin: center; 41 | } 42 | 43 | @keyframes rotator { 44 | 0% { 45 | transform: rotate(0deg); 46 | } 47 | 48 | 100% { 49 | transform: rotate(360deg); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/itchio.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-itchio { 4 | --pa-itchio-image-size: 10rem; 5 | --pa-itchio-padding: 0.5rem; 6 | --pa-itchio-background: var(--pa-color-basic-brightest); 7 | --pa-itchio-radius: var(--pa-border-radius-small); 8 | --pa-itchio-image-gutter: 1rem; 9 | --pa-itchio-title-size: var(--pa-font-size-large); 10 | --pa-itchio-title-weight: var(--pa-font-weight-medium); 11 | --pa-itchio-price-size: var(--pa-font-size-small); 12 | --pa-itchio-price-weight: var(--pa-font-weight-medium); 13 | 14 | @mixin shared-styles; 15 | 16 | &__container { 17 | font-family: var(--pa-font-family); 18 | background-color: var(--pa-itchio-background); 19 | border-radius: var(--pa-itchio-radius); 20 | padding: var(--pa-itchio-padding); 21 | } 22 | 23 | &__image { 24 | border-radius: var(--pa-itchio-radius); 25 | margin-right: var(--pa-itchio-image-gutter); 26 | max-width: var(--pa-itchio-image-size); 27 | } 28 | 29 | &__title { 30 | font-size: var(--pa-itchio-title-size); 31 | font-weight: var(--pa-itchio-title-weight); 32 | } 33 | 34 | &__price { 35 | font-size: var(--pa-itchio-price-size); 36 | font-weight: var(--pa-itchio-price-weight); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/itchio.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-itchio { 4 | --pa-itchio-image-size: 10rem; 5 | --pa-itchio-padding: 0.5rem; 6 | --pa-itchio-background: var(--pa-color-basic-brightest); 7 | --pa-itchio-radius: var(--pa-border-radius-small); 8 | --pa-itchio-image-gutter: 1rem; 9 | --pa-itchio-title-size: var(--pa-font-size-large); 10 | --pa-itchio-title-weight: var(--pa-font-weight-medium); 11 | --pa-itchio-price-size: var(--pa-font-size-small); 12 | --pa-itchio-price-weight: var(--pa-font-weight-medium); 13 | 14 | @mixin shared-styles; 15 | 16 | &__container { 17 | background-color: var(--pa-itchio-background); 18 | border-radius: var(--pa-itchio-radius); 19 | padding: var(--pa-itchio-padding); 20 | font-family: var(--pa-font-family); 21 | } 22 | 23 | &__image { 24 | border-radius: var(--pa-itchio-radius); 25 | margin-right: var(--pa-itchio-image-gutter); 26 | max-width: var(--pa-itchio-image-size); 27 | } 28 | 29 | &__title { 30 | font-size: var(--pa-itchio-title-size); 31 | font-weight: var(--pa-itchio-title-weight); 32 | } 33 | 34 | &__price { 35 | font-size: var(--pa-itchio-price-size); 36 | font-weight: var(--pa-itchio-price-weight); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hooks/post-install.hook.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra'; 2 | import glob from 'glob'; 3 | import mainPackageJson from '../package.json' assert { type: 'json' }; 4 | const dependencies = mainPackageJson.dependencies; 5 | const packagesJson = glob.sync(`./packages/**/package.json`); 6 | 7 | function copyMainDependencies(packageJson) { 8 | const data = fs.readFileSync(packageJson, 'utf8'); 9 | const rawDependencies = Object.entries(dependencies) 10 | .map(([key, value]) => `\n "${key}": "${value}"`) 11 | .join(','); 12 | const result = data.replace(/("dependencies": {)(.*)( },\r?\n? "peerDependencies)/gs, `$1${rawDependencies}\n$3`); 13 | 14 | fs.writeFileSync(packageJson, result, 'utf8'); 15 | } 16 | 17 | function copyThemes(packageJson) { 18 | const data = fs.readFileSync(packageJson, 'utf8'); 19 | const rawDependencies = Object.entries(dependencies) 20 | .map(([key, value]) => `\n "${key}": "${value}"`) 21 | .join(','); 22 | const result = data.replace(/("dependencies": {)(.*)( },\r?\n? "peerDependencies)/gs, `$1${rawDependencies}\n$3`); 23 | 24 | fs.writeFileSync(packageJson, result, 'utf8'); 25 | } 26 | 27 | packagesJson.forEach((packagesJson) => { 28 | copyMainDependencies(packagesJson); 29 | copyThemes(packagesJson); 30 | }); 31 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { initBreakpointChecker, setPlatform, setVersion, Platform } from './helpers'; 2 | import './styles/variables.css'; 3 | export { setDebugLevel, DebugLevel, addCodeLanguage, getPlatform, getVersion } from './helpers'; 4 | 5 | // Init Components 6 | export { default as Avatar } from './elements/components/avatar'; 7 | export { default as Breadcrumb } from './elements/components/breadcrumb'; 8 | export { default as Button } from './elements/components/button'; 9 | export { default as Code } from './elements/components/code'; 10 | export { default as Pill } from './elements/components/pill'; 11 | export { default as Spinner } from './elements/components/spinner'; 12 | export { default as Itchio } from './elements/enterprise/itchio'; 13 | export { default as useTooltipExtension } from './elements/extensions/tooltip'; 14 | // TODO this breaks command --element 15 | export { default as Toast, useToastExtension } from './elements/extensions/toast'; 16 | export { default as Column } from './elements/layout/column'; 17 | export { default as Container } from './elements/layout/container'; 18 | export { default as Row } from './elements/layout/row'; 19 | // End Components 20 | 21 | setPlatform(Platform.Default); 22 | setVersion('0.0.0'); 23 | initBreakpointChecker(); 24 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* Color Primary */ 3 | --pa-color-primary-brightest: #b9daff; 4 | --pa-color-primary-brighter: #a4cfff; 5 | --pa-color-primary-bright: #53a5ff; 6 | --pa-color-primary-normal: #017aff; 7 | --pa-color-primary-dark: #005fc8; 8 | --pa-color-primary-darker: #004590; 9 | --pa-color-primary-darkest: #002a58; 10 | 11 | /* Color Secondary */ 12 | --pa-color-secondary-brightest: #eeeaff; 13 | --pa-color-secondary-brighter: #cec1ff; 14 | --pa-color-secondary-bright: #ad99ff; 15 | --pa-color-secondary-normal: #6c47ff; 16 | --pa-color-secondary-dark: #3f0fff; 17 | --pa-color-secondary-darker: #2b00d6; 18 | --pa-color-secondary-darkest: #20009e; 19 | 20 | /* Color Tertiary */ 21 | --pa-color-tertiary-brightest: #fde2e8; 22 | --pa-color-tertiary-brighter: #fbbccb; 23 | --pa-color-tertiary-bright: #f896ad; 24 | --pa-color-tertiary-normal: #f34971; 25 | --pa-color-tertiary-dark: #f01448; 26 | --pa-color-tertiary-darker: #bf0d37; 27 | --pa-color-tertiary-darkest: #8b0928; 28 | 29 | /* Font */ 30 | --pa-font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif; 31 | 32 | /* Shadow */ 33 | --pa-shadow-normal: var(--pa-color-basic-bright) 0 1px 3px 0; 34 | } 35 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.hook.ts: -------------------------------------------------------------------------------- 1 | import { debug } from '~/helpers'; 2 | import { toastBus } from './toast.bus'; 3 | import './toast.css'; 4 | import { ToastPayload } from './toast.model'; 5 | 6 | const themes = {}; 7 | 8 | const actions: { 9 | [key: string]: (payload: ToastPayload) => void; 10 | } = {}; 11 | 12 | function actionFactory(name) { 13 | return (payload: ToastPayload) => { 14 | toastBus.publish({ 15 | id: `${Math.random()}`, 16 | ...payload 17 | }); 18 | }; 19 | } 20 | 21 | function createTheme(name: string) { 22 | const properties = ['background', 'foreground']; 23 | const theme = {}; 24 | 25 | properties.forEach((property) => (theme[property] = `var(--pa-toast-${property}-${name})`)); 26 | 27 | debug(`ToastService createTheme: ${name}: ${JSON.stringify(theme)}`); 28 | 29 | toastBus.register(); 30 | themes[name] = theme; 31 | actions[name] = actionFactory(name); 32 | } 33 | 34 | function triggerCustomAction(name: string, payload: ToastPayload) { 35 | return actions[name](payload); 36 | } 37 | 38 | export default function useToastExtension() { 39 | createTheme('success'); 40 | createTheme('error'); 41 | 42 | return { success: actions.success, error: actions.error, createTheme, trigger: triggerCustomAction }; 43 | } 44 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-preact.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | import { generateCodeSandboxLink } from './codesandbox.helper'; 3 | 4 | export function generatePreactCodeSandboxLink(options) { 5 | const { components, extensions, code, dependencies } = options; 6 | 7 | const previewCode = `import { ${components.join(', ')} ${ 8 | components.length > 0 && extensions.length > 0 ? ', ' : '' 9 | }${extensions.join(', ')} } from '@papanasi/preact'; 10 | import '@papanasi/preact/papanasi.css';${[...extensions, ''].join('(); \n')} 11 | 12 | export default class App extends Component { render() { return (${code} 13 | ); }} 14 | `; 15 | 16 | const demoCode = `import { Component, render } from "preact"; 17 | 18 | ${previewCode} 19 | 20 | render(, document.getElementById("root")); 21 | `.trim(); 22 | 23 | const projectDependencies = { 24 | ...dependencies, 25 | preact: '10.2.1', 26 | '@papanasi/preact': `${lernaJson.version}` 27 | }; 28 | 29 | const devDependencies = { 30 | 'preact-cli': '^1.4.1' 31 | }; 32 | 33 | const { url } = generateCodeSandboxLink({ 34 | demoCode, 35 | dependencies: projectDependencies, 36 | devDependencies 37 | }); 38 | 39 | return { url, content: previewCode }; 40 | } 41 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.lite.tsx: -------------------------------------------------------------------------------- 1 | import { For, onMount, onUnMount, useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './toast.css'; 3 | import type { ToastProps, ToastState } from './toast.model'; 4 | import { toastService } from './toast.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Toast(props: ToastProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return toastService.getClasses(props.disabled, props.className || props.classList); 12 | }, 13 | get toasts() { 14 | return toastService.getToasts(); 15 | }, 16 | toastSubscription: null 17 | }); 18 | 19 | onMount(() => { 20 | if (state.toastSubscription) { 21 | return; 22 | } 23 | 24 | // TODO: This approach doesnt work looks like is not reactive enough I will try other approach 25 | state.toastSubscription = toastService.subscribe(); 26 | }); 27 | 28 | onUnMount(() => { 29 | if (!state.toastSubscription) { 30 | return; 31 | } 32 | 33 | state.toastSubscription.unsubscribe(); 34 | }); 35 | 36 | return ( 37 |
38 | {(toast) =>
{toast.message}
}
39 | {props.children} 40 |
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /packages/solid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/solid", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Solid JS UI Library", 7 | "type": "module", 8 | "source": "./solid-index.tsx", 9 | "main": "dist/cjs/papanasi.js", 10 | "module": "dist/esm/papanasi.js", 11 | "types": "dist/types/papanasi.d.ts", 12 | "exports": { 13 | ".": { 14 | "solid": "./dist/index/index.js", 15 | "import": "./dist/esm/papanasi.js", 16 | "browser": "./dist/esm/papanasi.js", 17 | "require": "./dist/cjs/papanasi.js", 18 | "node": "./dist/cjs/papanasi.js" 19 | }, 20 | "./papanasi.css": { 21 | "import": "./dist/themes/papanasi.css", 22 | "require": "./dist/themes/papanasi.css" 23 | }, 24 | "./sketch.css": { 25 | "import": "./dist/themes/sketch.css", 26 | "require": "./dist/themes/sketch.css" 27 | } 28 | }, 29 | "dependencies": { 30 | "codejar": "^3.6.0", 31 | "copy-to-clipboard": "^3.3.2", 32 | "ssr-window": "^4.0.2" 33 | }, 34 | "files": [ 35 | "dist" 36 | ], 37 | "scripts": { 38 | "build": "rollup -c", 39 | "postbuild": "node ./copy-css.js" 40 | }, 41 | "publishConfig": { 42 | "access": "public" 43 | }, 44 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 45 | } 46 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-react.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | import { generateCodeSandboxLink } from './codesandbox.helper'; 3 | 4 | export function generateReactCodeSandboxLink(options) { 5 | const { components, extensions, code, dependencies } = options; 6 | 7 | const html = `
`; 8 | 9 | const previewCode = `import { ${components.join(', ')} ${ 10 | components.length > 0 && extensions.length > 0 ? ', ' : '' 11 | }${extensions.join(', ')} } from '@papanasi/react'; 12 | import '@papanasi/react/papanasi.css';${[...extensions, ''].join('(); \n')} 13 | 14 | const App = () => (${code} 15 | ); 16 | `; 17 | 18 | const demoCode = ` 19 | import React from 'react'; 20 | import ReactDOM from 'react-dom'; 21 | 22 | ${previewCode} 23 | 24 | ReactDOM.render( 25 | , 26 | document.getElementById("root") 27 | ) 28 | `.trim(); 29 | 30 | const projectDependencies = { 31 | ...dependencies, 32 | react: '16.8.0', 33 | 'react-dom': '16.8.0', 34 | '@papanasi/react': `${lernaJson.version}` 35 | }; 36 | 37 | const devDependencies = { 38 | 'react-scripts': 'latest' 39 | }; 40 | 41 | const { url } = generateCodeSandboxLink({ 42 | html, 43 | demoCode, 44 | dependencies: projectDependencies, 45 | devDependencies 46 | }); 47 | 48 | return { url, content: previewCode }; 49 | } 50 | -------------------------------------------------------------------------------- /src/elements/components/code/code.model.ts: -------------------------------------------------------------------------------- 1 | import { CodeJar } from '~/helpers'; 2 | import type { BaseProps, BaseState, Children } from '~/models'; 3 | 4 | export interface ICodeService { 5 | styles: HTMLLinkElement[]; 6 | jar: CodeJar; 7 | currentThemeIndex: number; 8 | hljs: any; 9 | getClasses(language: string, className: string): { base: string; editor: string }; 10 | initialize(codeRef: HTMLElement, language: string, theme: CodeTheme): Promise; 11 | destroy(): void; 12 | update(code: string): void; 13 | onUpdate(callback: (code: string) => void): void; 14 | setEditable(codeRef: HTMLElement, editable: boolean): Promise; 15 | copy(code: string): Promise; 16 | } 17 | 18 | export type CodeLink = { label: string; url: string; icon: string }; 19 | 20 | export interface CodeProps extends BaseProps { 21 | editable?: boolean; 22 | language: string; 23 | theme: CodeTheme; 24 | code: string; 25 | disableCopy?: boolean; 26 | slotCopy?: Children; 27 | links?: CodeLink[]; 28 | onUpdate?: (code: string) => void; 29 | } 30 | 31 | export interface CodeState extends BaseState { 32 | classes: { base: string; editor: string }; 33 | codeService: ICodeService; 34 | value: (x: T, y: string) => string; 35 | } 36 | 37 | export const codeThemes = ['default', 'dark', 'atom-one-light', 'atom-one-dark', 'github', 'monokai'] as const; 38 | 39 | export type CodeTheme = (typeof codeThemes)[number]; 40 | -------------------------------------------------------------------------------- /packages/svelte/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/svelte", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Svelte UI Library", 7 | "type": "module", 8 | "main": "./dist/index.js", 9 | "module": "./dist/index.js", 10 | "svelte": "./src/index.ts", 11 | "types": "./dist/index.d.ts", 12 | "exports": { 13 | ".": { 14 | "import": "./dist/index.js", 15 | "require": "./dist/index.js" 16 | }, 17 | "./papanasi.css": { 18 | "import": "./dist/themes/papanasi.css", 19 | "require": "./dist/themes/papanasi.css" 20 | }, 21 | "./sketch.css": { 22 | "import": "./dist/themes/sketch.css", 23 | "require": "./dist/themes/sketch.css" 24 | } 25 | }, 26 | "dependencies": { 27 | "@trutoo/event-bus": "^2.2.0", 28 | "codejar": "^3.7.0", 29 | "copy-to-clipboard": "^3.3.3", 30 | "highlight.js": "^11.7.0", 31 | "ofetch": "^1.0.1", 32 | "ssr-window": "^4.0.2" 33 | }, 34 | "peerDependencies": { 35 | "highlight.js": "^11.6.0", 36 | "svelte": "^3.x" 37 | }, 38 | "files": [ 39 | "dist", 40 | "src" 41 | ], 42 | "scripts": { 43 | "build": "svelte-kit sync && svelte-package --input src --output dist", 44 | "postbuild": "copyfiles ../../.themes/** ./dist/themes --flat" 45 | }, 46 | "publishConfig": { 47 | "access": "public" 48 | }, 49 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 50 | } 51 | -------------------------------------------------------------------------------- /compiler/platforms/webcomponents.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import prependFile from 'prepend-file'; 3 | import compiler from '../base.compiler.js'; 4 | 5 | const DEFAULT_OPTIONS = { 6 | target: 'webcomponents', 7 | extension: 'ts', 8 | state: '', 9 | styles: '' 10 | }; 11 | 12 | (async () => { 13 | function customReplace(props) { 14 | const { outFile } = props; 15 | 16 | // Ignore types 17 | prependFile.sync(outFile, '//@ts-nocheck \n'); 18 | 19 | // Make component exportable 20 | const data = fs.readFileSync(outFile, 'utf8'); 21 | const result = data 22 | // Fix class name 23 | .replace(/class /, 'export default class ') 24 | 25 | .replace( 26 | /customElements\.define\("(.*)",(.*)\);/g, 27 | 'customElements.get("pa-$1") || customElements.define("pa-$1", $2);' 28 | ) 29 | // Fix part selectors 30 | .replace(/class=/g, 'part=') 31 | .replace(/el\.setAttribute\("class"/g, 'el.setAttribute("part"') 32 | .replace(/el\.className ?= ?\n?(.*);/g, 'el.setAttribute("part",$1);') 33 | // Replace classname for class 34 | .replace(/\.className/g, '.class') 35 | // Enable children 36 | .replace( 37 | /this\.props\.children/, 38 | 'this.shadowRoot.querySelector("slot").assignedNodes().filter((x,i) => i % 2 !== 0 )' 39 | ); 40 | 41 | fs.writeFileSync(outFile, result, 'utf8'); 42 | } 43 | 44 | await compiler.compile({ ...DEFAULT_OPTIONS, customReplace }); 45 | })(); 46 | -------------------------------------------------------------------------------- /packages/preact/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/preact", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Preact UI Library", 7 | "type": "module", 8 | "main": "./dist/papanasi-preact.umd.js", 9 | "module": "./dist/papanasi-preact.es.js", 10 | "types": "./dist/index.d.ts", 11 | "exports": { 12 | ".": { 13 | "import": "./dist/papanasi-preact.es.js", 14 | "require": "./dist/papanasi-preact.umd.js" 15 | }, 16 | "./papanasi.css": { 17 | "import": "./dist/themes/papanasi.css", 18 | "require": "./dist/themes/papanasi.css" 19 | }, 20 | "./sketch.css": { 21 | "import": "./dist/themes/sketch.css", 22 | "require": "./dist/themes/sketch.css" 23 | } 24 | }, 25 | "dependencies": { 26 | "@trutoo/event-bus": "^2.2.0", 27 | "codejar": "^3.7.0", 28 | "copy-to-clipboard": "^3.3.3", 29 | "highlight.js": "^11.7.0", 30 | "ofetch": "^1.0.1", 31 | "ssr-window": "^4.0.2" 32 | }, 33 | "peerDependencies": { 34 | "preact": "^10.2.x" 35 | }, 36 | "files": [ 37 | "dist" 38 | ], 39 | "scripts": { 40 | "prebuild": "yarn install", 41 | "build": "rollup -c", 42 | "postbuild": "copyfiles ../../.themes/** ./dist/themes --flat && rimraf ./dist/papanasi-preact.es.d.ts&& rimraf ./dist/papanasi-preact.umd.d.ts" 43 | }, 44 | "publishConfig": { 45 | "access": "public" 46 | }, 47 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 48 | } 49 | -------------------------------------------------------------------------------- /src/elements/components/avatar/avatar.lite.tsx: -------------------------------------------------------------------------------- 1 | import { onInit, Show, useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './avatar.css'; 3 | import type { AvatarProps, AvatarState } from './avatar.model'; 4 | import { avatarService } from './avatar.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Avatar(props: AvatarProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return avatarService.getClasses(props.variant, props.disabled, props.className || props.classList); 12 | }, 13 | get initials() { 14 | return avatarService.getInitials(props.name); 15 | }, 16 | get source() { 17 | return avatarService.getSource(props.url, props.unavatar); 18 | }, 19 | styles: { container: null } 20 | }); 21 | 22 | onInit(() => { 23 | async function getData() { 24 | state.styles = await avatarService.getStyles(props.name, props.variant); 25 | } 26 | 27 | getData(); 28 | }); 29 | 30 | return ( 31 |
32 | 33 |
34 | 35 | {props.name} 36 | 37 | 38 | {state.initials} 39 | 40 |
41 |
42 |
43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/elements/components/breadcrumb/breadcrumb.lite.tsx: -------------------------------------------------------------------------------- 1 | import { For, Show, useMetadata, useStore } from '@builder.io/mitosis'; 2 | import './breadcrumb.css'; 3 | import type { BreadcrumbProps, BreadcrumbState } from './breadcrumb.model'; 4 | import { breadcrumbService } from './breadcrumb.service'; 5 | 6 | useMetadata({ isAttachedToShadowDom: true }); 7 | 8 | export default function Breadcrumb(props: BreadcrumbProps) { 9 | const state = useStore({ 10 | get classes() { 11 | return breadcrumbService.getClasses(props.className || props.classList); 12 | }, 13 | get separator() { 14 | return props.separator || '/'; 15 | } 16 | }); 17 | 18 | return ( 19 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | Please delete options that are not relevant. 10 | 11 | - [ ] Bug fix 12 | - [ ] New feature 13 | - [ ] Component 14 | 15 | **Why Papanasi needs this component** 16 | 17 | Explain the reasons behind the component. 18 | 19 | **Are you the author/collaborator of dependencies used by this component?** 20 | - [ ] Yes, I'm the author 21 | - [ ] Yes, I'm not the author but I'm collaborating with the project 22 | - [ ] No 23 | 24 | **CodeSandbox demos** 25 | 26 | We need to be sure that this component works, we have prepared some Code Sandbox that you can use as template and paste your dist files inside `papanasi` folder: 27 | - Angular: https://codesandbox.io/s/papanasi-angular-pr-kb3j3b 28 | - Preact: https://codesandbox.io/s/papanasi-preact-pr-3tzvtk 29 | - Qwik: https://stackblitz.com/edit/qwik-starter-i6prxe 30 | - React: https://codesandbox.io/s/papanasi-react-pr-3ymi5n 31 | - Solid: https://codesandbox.io/s/papanasi-solid-pr-bnvs7l 32 | - Svelte: https://codesandbox.io/s/papanasi-svelte-pr-5fdimr 33 | - Vue: https://codesandbox.io/s/papanasi-vue-pr-moq18f 34 | - WebComponents: https://codesandbox.io/s/papanasi-webcomponents-pr-nsnwo2 35 | 36 | **Screenshots and demos** 37 | 38 | Add the necessary screenshots and demos required to understand this component. 39 | -------------------------------------------------------------------------------- /packages/angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/angular", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Angular UI Library", 7 | "type": "module", 8 | "main": "./dist/papanasi-angular.umd.js", 9 | "module": "./dist/papanasi-angular.es.js", 10 | "types": "./dist/index.d.ts", 11 | "exports": { 12 | ".": { 13 | "import": "./dist/papanasi-angular.es.js", 14 | "require": "./dist/papanasi-angular.umd.js" 15 | }, 16 | "./papanasi.css": { 17 | "import": "./dist/themes/papanasi.css", 18 | "require": "./dist/themes/papanasi.css" 19 | }, 20 | "./sketch.css": { 21 | "import": "./dist/themes/sketch.css", 22 | "require": "./dist/themes/sketch.css" 23 | } 24 | }, 25 | "dependencies": { 26 | "@trutoo/event-bus": "^2.2.0", 27 | "codejar": "^3.7.0", 28 | "copy-to-clipboard": "^3.3.3", 29 | "highlight.js": "^11.7.0", 30 | "ofetch": "^1.0.1", 31 | "ssr-window": "^4.0.2" 32 | }, 33 | "peerDependencies": { 34 | "@angular/common": ">=12.0.0", 35 | "@angular/core": ">=12.0.0" 36 | }, 37 | "files": [ 38 | "dist" 39 | ], 40 | "scripts": { 41 | "build": "rollup -c", 42 | "postbuild": "copyfiles ../../.themes/** ./dist/themes --flat && renamer --find papanasi-angular.es.d.ts --replace index.d.ts ./dist/* --silent && rimraf ./dist/papanasi-angular.umd.d.ts" 43 | }, 44 | "publishConfig": { 45 | "access": "public" 46 | }, 47 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 48 | } 49 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-qwik.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | 3 | export function generateQwikCodeSandboxLink(options) { 4 | const { components, extensions, code, dependencies } = options; 5 | 6 | const previewCode = `import { ${components.join(', ')} ${ 7 | components.length > 0 && extensions.length > 0 ? ', ' : '' 8 | }${extensions.join(', ')} } from '@papanasi/qwik'; 9 | import '@papanasi/qwik/style.css'; 10 | import '@papanasi/qwik/papanasi.css';${[...extensions, ''].join('(); \n')} 11 | 12 | export default component$(() => { 13 | return (${code} 14 | 15 | ); 16 | }); 17 | `; 18 | 19 | const demoCode = `import { Component, render } from "qwik"; 20 | 21 | ${previewCode} 22 | 23 | render(, document.getElementById("root")); 24 | `.trim(); 25 | 26 | const projectDependencies = { 27 | ...dependencies, 28 | '@builder.io/qwik': '0.9.0', 29 | '@papanasi/qwik': `${lernaJson.version}`, 30 | 'highlight.js': '^11.6.0' 31 | }; 32 | 33 | const devDependencies = { 34 | 'preact-cli': '^1.4.1' 35 | }; 36 | 37 | // const { url } = generateCodeSandboxLink({ 38 | // demoCode, 39 | // dependencies: projectDependencies, 40 | // devDependencies 41 | // }); 42 | 43 | // Temporal url meanwhile https://github.com/BuilderIO/qwik/issues/1644 44 | const url = 45 | 'https://stackblitz.com/edit/qwik-starter-i6prxe?file=src%2Fglobal.css,src%2Froot.tsx,package.json,vite.config.ts'; 46 | 47 | return { url, content: previewCode }; 48 | } 49 | -------------------------------------------------------------------------------- /src/helpers/color.helper.ts: -------------------------------------------------------------------------------- 1 | // Note: Some helpers are from https://gist.github.com/mjackson/5311256 2 | 3 | function random(min, max) { 4 | return Math.floor(Math.random() * (max - min + 1) + min); 5 | } 6 | 7 | function hue2rgb(p: number, q: number, t: number) { 8 | if (t < 0) t += 1; 9 | if (t > 1) t -= 1; 10 | if (t < 1 / 6) return p + (q - p) * 6 * t; 11 | if (t < 1 / 2) return q; 12 | if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 13 | return p; 14 | } 15 | 16 | function hsl2rgba(rawH: number, rawS: number, rawL: number, alpha = 1): string { 17 | const h = rawH / 360; 18 | const s = rawS / 110; 19 | const l = rawL / 85; 20 | let r, g, b; 21 | 22 | if (s === 0) { 23 | r = g = b = l; // achromatic 24 | } else { 25 | const q = l < 0.5 ? l * (1 + s) : l + s - l * s; 26 | const p = 2 * l - q; 27 | 28 | r = hue2rgb(p, q, h + 1.0 / 3.0); 29 | g = hue2rgb(p, q, h); 30 | b = hue2rgb(p, q, h - 1.0 / 3.0); 31 | } 32 | 33 | return `rgba(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(b * 255)}, ${alpha})`; 34 | } 35 | 36 | function hashCode(text: string) { 37 | let hash = 0; 38 | for (let i = 0; i < text.length; i++) { 39 | hash = text.charCodeAt(i) + ((hash << 5) - hash); 40 | } 41 | return hash; 42 | } 43 | 44 | export async function randomColor(text: string, alpha = 0.5) { 45 | const h = hashCode(text) % 360; 46 | const s = random(55, 90); 47 | const l = random(40, 60); 48 | 49 | return { 50 | foreground: hsl2rgba(h, s, l * 0.75, 1), 51 | background: hsl2rgba(h, s, l * 1.1, alpha) 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /.github/workflows/azure-static-web-apps-witty-plant-07a086e03.yml: -------------------------------------------------------------------------------- 1 | name: Azure Static Web Apps CI/CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | build_and_deploy_job: 9 | if: github.event_name == 'push' 10 | runs-on: ubuntu-latest 11 | name: Build and Deploy Job 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | submodules: true 16 | 17 | - uses: actions/setup-node@v3 18 | with: 19 | node-version: 18 20 | 21 | - name: install, build 22 | run: | 23 | yarn 24 | yarn build --no-lint 25 | yarn build-storybook 26 | 27 | - name: Build And Deploy 28 | id: builddeploy 29 | uses: Azure/static-web-apps-deploy@v1 30 | with: 31 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_WITTY_PLANT_07A086E03 }} 32 | repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) 33 | action: 'upload' 34 | skip_app_build: true 35 | skip_api_build: true 36 | app_location: '/storybook-static' # App source code path 37 | build_pr: 38 | if: github.event_name != 'push' || (github.event_name == 'pull_request') 39 | runs-on: ubuntu-latest 40 | name: Build PR 41 | steps: 42 | - uses: actions/checkout@v2 43 | with: 44 | submodules: true 45 | 46 | - name: install, build, test 47 | run: | 48 | yarn 49 | yarn build 50 | yarn build-storybook 51 | yarn test 52 | -------------------------------------------------------------------------------- /packages/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/vue", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Vue UI Library", 7 | "type": "module", 8 | "main": "./dist/papanasi-vue.umd.js", 9 | "module": "./dist/papanasi-vue.es.js", 10 | "types": "./dist/index.d.ts", 11 | "exports": { 12 | ".": { 13 | "import": "./dist/papanasi-vue.es.js", 14 | "require": "./dist/papanasi-vue.umd.js" 15 | }, 16 | "./papanasi.css": { 17 | "import": "./dist/themes/papanasi.css", 18 | "require": "./dist/themes/papanasi.css" 19 | }, 20 | "./sketch.css": { 21 | "import": "./dist/themes/sketch.css", 22 | "require": "./dist/themes/sketch.css" 23 | } 24 | }, 25 | "dependencies": { 26 | "@trutoo/event-bus": "^2.2.0", 27 | "codejar": "^3.7.0", 28 | "copy-to-clipboard": "^3.3.3", 29 | "highlight.js": "^11.7.0", 30 | "ofetch": "^1.0.1", 31 | "ssr-window": "^4.0.2" 32 | }, 33 | "peerDependencies": { 34 | "vue": "^3.x" 35 | }, 36 | "files": [ 37 | "dist" 38 | ], 39 | "scripts": { 40 | "build": "rollup -c", 41 | "postbuild": "copyfiles ../../.themes/** ./dist/themes --flat && rimraf --glob ./dist/*.d.ts && npm run typings", 42 | "typings": "vue-tsc --declaration --emitDeclarationOnly --project . --outFile ./dist/index.d.ts && replace 'packages/vue/src/index' '@papanasi/vue' ./dist/index.d.ts --silent" 43 | }, 44 | "publishConfig": { 45 | "access": "public" 46 | }, 47 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 48 | } 49 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/variables.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Patrick+Hand&display=swap'); 2 | 3 | :root { 4 | /* Border */ 5 | --pa-border-radius-small: 255px 15px 225px 15px/15px 225px 15px 255px; 6 | --pa-border-width-small: 2px; 7 | 8 | /* Color Primary */ 9 | --pa-color-primary-brightest: #dbdbdb; 10 | --pa-color-primary-brighter: #d1d1d1; 11 | --pa-color-primary-bright: #a8a8a8; 12 | --pa-color-primary-normal: #5c5c5c; 13 | --pa-color-primary-dark: #4e4d4d; 14 | --pa-color-primary-darker: #3e3e3e; 15 | --pa-color-primary-darkest: #2b2b2b; 16 | 17 | /* Color Secondary */ 18 | --pa-color-secondary-brightest: #b7b7b7; 19 | --pa-color-secondary-brighter: #7c7c7c; 20 | --pa-color-secondary-bright: #615f5f; 21 | --pa-color-secondary-normal: #333333; 22 | --pa-color-secondary-dark: #282828; 23 | --pa-color-secondary-darker: #201f1f; 24 | --pa-color-secondary-darkest: #0e0d0d; 25 | 26 | /* Color Tertiary */ 27 | --pa-color-tertiary-brightest: #d0daff; 28 | --pa-color-tertiary-brighter: #7c91e0; 29 | --pa-color-tertiary-bright: #607ad9; 30 | --pa-color-tertiary-normal: #3057e1; 31 | --pa-color-tertiary-dark: #2140af; 32 | --pa-color-tertiary-darker: #1b3184; 33 | --pa-color-tertiary-darkest: #172864; 34 | 35 | /* Font */ 36 | --pa-font-family: 'Patrick Hand', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif; 37 | --pa-font-size-normal: 1.05rem; 38 | 39 | /* Shadow */ 40 | --pa-shadow-normal: none; 41 | 42 | /* Stripe */ 43 | --pa-stripe-angle: 135deg; 44 | --pa-stripe-size: 5.66px 5.66px; 45 | } 46 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | const DISABLED = 0; 2 | const WARNING = 1; 3 | const ERROR = 2; 4 | 5 | module.exports = { 6 | parser: '@typescript-eslint/parser', 7 | // Specifies the ESLint parser 8 | plugins: ['@builder.io/mitosis'], 9 | extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'plugin:storybook/recommended'], 10 | parserOptions: { 11 | ecmaVersion: 2018, 12 | // Allows for the parsing of modern ECMAScript features 13 | sourceType: 'module', 14 | // Allows for the use of imports 15 | ecmaFeatures: { 16 | jsx: true 17 | } 18 | }, 19 | rules: { 20 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs 21 | // "@typescript-eslint/explicit-function-return-type": ["error", { allowExpressions: true }], 22 | '@typescript-eslint/camelcase': DISABLED, 23 | '@typescript-eslint/ban-ts-comment': DISABLED, 24 | '@typescript-eslint/interface-name-prefix': DISABLED, 25 | '@typescript-eslint/no-empty-interface': DISABLED, 26 | '@typescript-eslint/no-var-requires': DISABLED, 27 | 'react/prop-types': DISABLED, 28 | 'react/prop': DISABLED, 29 | '@builder.io/mitosis/no-unused-expressions': DISABLED, 30 | '@builder.io/mitosis/no-var-name-same-as-state-property': ERROR, 31 | '@builder.io/mitosis/jsx-callback-arg-name': ERROR, 32 | '@builder.io/mitosis/jsx-callback-arrow-function': ERROR, 33 | '@builder.io/mitosis/no-assign-props-to-state': ERROR, 34 | '@builder.io/mitosis/no-conditional-logic-in-component-render': ERROR, 35 | '@builder.io/mitosis/no-state-destructuring': ERROR 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/elements/layout/column/column.css: -------------------------------------------------------------------------------- 1 | @import '~/styles/build.css'; 2 | 3 | @define-mixin column $size, $columns { 4 | flex: 0 0 calc($size / $columns * 100% - var(--pa-grid-gutter-horizontal) * 2); 5 | max-width: calc($size / $columns * 100% - var(--pa-grid-gutter-horizontal) * 2); 6 | } 7 | 8 | @define-mixin column-content { 9 | flex: 0 0 auto; 10 | width: auto; 11 | max-width: none; 12 | display: flex; 13 | } 14 | 15 | @define-mixin column-fill { 16 | display: flex; 17 | flex-basis: 0; 18 | flex-grow: 1; 19 | max-width: 100%; 20 | width: 100%; 21 | } 22 | 23 | @define-mixin column-hide { 24 | display: none; 25 | } 26 | 27 | .pa-column { 28 | @mixin column-fill; 29 | 30 | margin-bottom: var(--pa-grid-gutter-vertical); 31 | margin-left: var(--pa-grid-gutter-horizontal); 32 | margin-right: var(--pa-grid-gutter-horizontal); 33 | margin-top: var(--pa-grid-gutter-vertical); 34 | 35 | &--centered { 36 | justify-content: center; 37 | align-items: center; 38 | align-content: center; 39 | } 40 | 41 | @each $breakpoint in var(--internal-breakpoints) { 42 | @each $value in var(--internal-columns) { 43 | @mixin breakpoint-modifier $breakpoint, $value { 44 | @mixin column $value, var(--internal-columns-total); 45 | display: flex; 46 | } 47 | } 48 | 49 | @mixin breakpoint-modifier $breakpoint, content { 50 | @mixin column-content; 51 | } 52 | 53 | @mixin breakpoint-modifier $breakpoint, fill { 54 | @mixin column-fill; 55 | } 56 | 57 | @mixin breakpoint-modifier $breakpoint, hide { 58 | @mixin column-hide; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/react", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi React UI Library", 7 | "type": "module", 8 | "main": "./dist/papanasi-react.umd.js", 9 | "module": "./dist/papanasi-react.es.js", 10 | "types": "./dist/index.d.ts", 11 | "exports": { 12 | ".": { 13 | "import": "./dist/papanasi-react.es.js", 14 | "require": "./dist/papanasi-react.umd.js" 15 | }, 16 | "./papanasi.css": { 17 | "import": "./dist/themes/papanasi.css", 18 | "require": "./dist/themes/papanasi.css" 19 | }, 20 | "./sketch.css": { 21 | "import": "./dist/themes/sketch.css", 22 | "require": "./dist/themes/sketch.css" 23 | } 24 | }, 25 | "dependencies": { 26 | "@trutoo/event-bus": "^2.2.0", 27 | "codejar": "^3.7.0", 28 | "copy-to-clipboard": "^3.3.3", 29 | "highlight.js": "^11.7.0", 30 | "ofetch": "^1.0.1", 31 | "ssr-window": "^4.0.2" 32 | }, 33 | "peerDependencies": { 34 | "react": ">=16.8.0", 35 | "react-dom": ">=16.8.0" 36 | }, 37 | "files": [ 38 | "dist" 39 | ], 40 | "scripts": { 41 | "prebuild": "yarn install", 42 | "build": "rollup -c", 43 | "postbuild": "copyfiles ../../.themes/** ./dist/themes --flat && rimraf --glob ./dist/*.d.ts && npm run typings", 44 | "typings": "tsc --declaration --emitDeclarationOnly --project . --outFile ./dist/index.d.ts && replace '\"index\"' '@papanasi/react' ./dist/index.d.ts --silent" 45 | }, 46 | "publishConfig": { 47 | "access": "public" 48 | }, 49 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 50 | } 51 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/code.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-code { 4 | @mixin shared-styles; 5 | 6 | border-radius: var(--pa-border-radius-small); 7 | box-shadow: var(--pa-shadow-normal); 8 | border: var(--pa-border-width-small) solid var(--pa-color-basic-brighter); 9 | width: 100%; 10 | overflow: hidden; 11 | 12 | &__actions { 13 | font-family: var(--pa-font-family); 14 | background: var(--pa-color-basic-brightest); 15 | backdrop-filter: blur(2px); 16 | } 17 | 18 | &__action { 19 | background-color: var(--pa-color-basic-brightest); 20 | border: var(--pa-border-width-small) solid var(--pa-color-basic-bright); 21 | border-right: 0; 22 | border-bottom: 0; 23 | transition-duration: var(--pa-transition-duration-normal); 24 | transition-property: var(--pa-transition-colors); 25 | 26 | &:hover { 27 | background-color: var(--pa-color-basic-brighter); 28 | } 29 | 30 | &--text:hover { 31 | background-color: var(--pa-color-basic-brightest); 32 | } 33 | 34 | &:nth-child(1) { 35 | border-top-left-radius: var(--pa-border-radius-small); 36 | 37 | &:hover { 38 | background-color: inherit; 39 | } 40 | } 41 | } 42 | 43 | &__link { 44 | color: var(--pa-color-basic-darkest); 45 | font-size: var(--pa-font-size-small); 46 | font-weight: var(--pa-font-weight-black); 47 | text-decoration: none; 48 | } 49 | 50 | .language-css, 51 | .language-scss { 52 | .hljs-number { 53 | @mixin background-opacity var(--number-color), 0.05; 54 | 55 | color: var(--number-color); 56 | filter: brightness(0.9); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/qwik/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/qwik", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Qwik UI Library", 7 | "type": "module", 8 | "main": "./lib/index.qwik.mjs", 9 | "qwik": "./lib/index.qwik.mjs", 10 | "module": "./lib/index.qwik.mjs", 11 | "types": "./types/index.d.ts", 12 | "exports": { 13 | ".": { 14 | "import": "./lib/index.qwik.mjs", 15 | "require": "./lib/index.qwik.cjs", 16 | "types": "./types/index.d.ts" 17 | }, 18 | "./style.css": { 19 | "import": "./lib/style.css", 20 | "require": "./lib/style.css" 21 | }, 22 | "./papanasi.css": { 23 | "import": "./lib/themes/papanasi.css", 24 | "require": "./lib/themes/papanasi.css" 25 | }, 26 | "./sketch.css": { 27 | "import": "./lib/themes/sketch.css", 28 | "require": "./lib/themes/sketch.css" 29 | } 30 | }, 31 | "dependencies": { 32 | "@trutoo/event-bus": "^2.2.0", 33 | "codejar": "^3.7.0", 34 | "copy-to-clipboard": "^3.3.3", 35 | "highlight.js": "^11.7.0", 36 | "ofetch": "^1.0.1", 37 | "ssr-window": "^4.0.2" 38 | }, 39 | "peerDependencies": { 40 | "@builder.io/qwik": "^0.x" 41 | }, 42 | "files": [ 43 | "lib", 44 | "types" 45 | ], 46 | "scripts": { 47 | "prebuild": "yarn install", 48 | "build": "qwik build", 49 | "build.lib": "vite build --mode lib", 50 | "build.types": "tsc --emitDeclarationOnly", 51 | "postbuild": "copyfiles ../../.themes/** ./lib/themes --flat" 52 | }, 53 | "publishConfig": { 54 | "access": "public" 55 | }, 56 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 57 | } 58 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/code.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-code { 4 | @mixin shared-styles; 5 | 6 | border-radius: var(--pa-border-radius-small); 7 | box-shadow: var(--pa-shadow-normal); 8 | border: var(--pa-border-width-small) solid var(--pa-color-basic-brighter); 9 | width: 100%; 10 | overflow: hidden; 11 | 12 | &__actions { 13 | font-family: var(--pa-font-family); 14 | background: var(--pa-color-basic-brightest); 15 | backdrop-filter: blur(2px); 16 | } 17 | 18 | &__action { 19 | background-color: var(--pa-color-basic-brightest); 20 | border: var(--pa-border-width-small) solid var(--pa-color-basic-bright); 21 | border-right: 0; 22 | border-bottom: 0; 23 | transition-duration: var(--pa-transition-duration-normal); 24 | transition-property: var(--pa-transition-colors); 25 | padding-bottom: 0.5rem; 26 | padding-top: 0.15rem; 27 | 28 | &:hover { 29 | background-color: var(--pa-color-basic-brighter); 30 | } 31 | 32 | &--text:hover { 33 | background-color: var(--pa-color-basic-brightest); 34 | } 35 | 36 | &:nth-child(1) { 37 | border-top-left-radius: var(--pa-border-radius-small); 38 | 39 | &:hover { 40 | background-color: inherit; 41 | } 42 | } 43 | } 44 | 45 | &__link { 46 | color: var(--pa-color-basic-darkest); 47 | font-size: var(--pa-font-size-small); 48 | font-weight: var(--pa-font-weight-black); 49 | text-decoration: none; 50 | } 51 | 52 | .language-css, 53 | .language-scss { 54 | .hljs-number { 55 | @mixin background-opacity var(--number-color), 0.05; 56 | 57 | color: var(--number-color); 58 | filter: brightness(0.9); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SPONSORS.md: -------------------------------------------------------------------------------- 1 | # Sponsors 2 | 3 | An sponsor is a person, a community or a company who is supporting Papanasi with $9 per month [via GitHub Sponsors](https://github.com/sponsors/ckgrafico). Every Sponsor will appear at: 4 | 5 | - Papanasi [website](https://papanasi.js.org) 6 | - The [README](https://github.com/ckgrafico/papanasi#sponsors) of the project 7 | - All npmjs.com packages [Angular](https://www.npmjs.com/package/@papanasi/angular), [Preact](https://www.npmjs.com/package/@papanasi/preact), [Qwik](https://www.npmjs.com/package/@papanasi/qwik), [React](https://www.npmjs.com/package/@papanasi/react), [Solid](https://www.npmjs.com/package/@papanasi/solid), [Svelte](https://www.npmjs.com/package/@papanasi/svelte),[Vue](https://www.npmjs.com/package/@papanasi/vue), [Web Components](https://www.npmjs.com/package/@papanasi/webcomponents) 8 | - This document 9 | 10 | 11 | All sponsors have priority support via GitHub issues. 12 | The sponsors are sorted by `date` in `ascending`. 13 | Don't hesitate to contact me if you have any question about sponsors, you can do it via [email](mailto:papanasi@ckgrafico.com) or [Twitter DM](https://twitter.com/ckgrafico) 14 | 15 | # How to become a sponsor 16 | 17 | 1. Set up the $9 per month sponsorship [via GitHub Sponsors](https://github.com/sponsors/ckgrafico) 18 | 2. Send your logo and link to papanasi@ckgrafico.com and I will publish it fast. 19 | 20 | # Our Sponsors 21 | 22 | 23 | 24 | 25 | 27 |

Sponsor the project

HelpDev
26 |
28 | -------------------------------------------------------------------------------- /.storybook/main.cjs: -------------------------------------------------------------------------------- 1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 2 | const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); 3 | 4 | module.exports = { 5 | stories: ['../docs/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'], 6 | staticDirs: ['../.themes'], 7 | core: { 8 | builder: 'webpack4' 9 | }, 10 | addons: [ 11 | '@storybook/addon-links', 12 | '@storybook/addon-essentials', 13 | '@storybook/addon-interactions', 14 | '@storybook/addon-postcss', 15 | '@a110/storybook-expand-all' 16 | ], 17 | framework: '@storybook/react', 18 | webpackFinal: async (config, options) => { 19 | // Extract css files 20 | const cssRule = config.module.rules.find((x) => x.test.toString().includes('css')); 21 | config.plugins.unshift(new MiniCssExtractPlugin()); 22 | 23 | const use = cssRule.use.filter((x) => !x.includes || !x.includes('style-loader')); 24 | use.unshift(MiniCssExtractPlugin.loader); 25 | cssRule.use = use.filter((x) => !x?.loader?.includes('style-loader')); 26 | 27 | config.module.rules.push({ 28 | test: /\.mjs$/, 29 | include: /node_modules/, 30 | type: 'javascript/auto' 31 | }); 32 | 33 | config.module.rules.push({ 34 | test: /code\.tsx$/, 35 | loader: 'string-replace-loader', 36 | options: { 37 | // There is an error on storybook prism implementation and we cannot use Promise.resolve(); 46 | 47 | config.resolve.plugins = [new TsconfigPathsPlugin()]; 48 | 49 | config.watch = false; 50 | 51 | options.watchOptions = { ignored: /src/ }; 52 | 53 | return config; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-solid.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | import { generateCodeSandboxLink } from './codesandbox.helper'; 3 | 4 | export function generateSolidCodeSandboxLink(options) { 5 | const { components, extensions, code, dependencies } = options; 6 | 7 | const html = `
8 | `; 9 | 10 | const previewCode = `import { ${components.join(', ')} ${ 11 | components.length > 0 && extensions.length > 0 ? ', ' : '' 12 | }${extensions.join(', ')} } from '@papanasi/solid'; 13 | import '@papanasi/solid/papanasi.css';${[...extensions, ''].join('(); \n')} 14 | 15 | const App: Component = () => (${code} 16 | ); 17 | `; 18 | 19 | const demoCode = ` 20 | import { Component } from "solid-js"; 21 | import { render } from "solid-js/web"; 22 | 23 | ${previewCode} 24 | 25 | render(() => , document.getElementById("app")); 26 | `.trim(); 27 | 28 | const extraFiles = { 29 | '.babelrc': { 30 | content: `{ 31 | "presets": [ 32 | "env", 33 | "babel-preset-solid", 34 | "@babel/preset-typescript" 35 | ] 36 | }` 37 | } 38 | }; 39 | 40 | const projectDependencies = { 41 | ...dependencies, 42 | '@babel/core': '7.14.6', 43 | '@babel/preset-typescript': '7.14.5', 44 | 'babel-preset-solid': '1.0.0', 45 | 'solid-js': '1.4.3', 46 | '@papanasi/solid': `${lernaJson.version}` 47 | }; 48 | 49 | const devDependencies = { 50 | 'parcel-bundler': '^1.6.1', 51 | typescript: '^4.2.0' 52 | }; 53 | 54 | const { url } = generateCodeSandboxLink({ 55 | html, 56 | demoCode, 57 | dependencies: projectDependencies, 58 | devDependencies, 59 | extraFiles, 60 | isTypescript: true 61 | }); 62 | 63 | return { url, content: previewCode }; 64 | } 65 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/avatar.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-avatar { 4 | --pa-avatar-size: 3rem; 5 | --pa-avatar-padding: 0.25rem; 6 | --pa-avatar-radius: 100%; 7 | --pa-avatar-border-width: var(--pa-border-width-small); 8 | --pa-avatar-initials-weight: var(--pa-font-weight-medium); 9 | --pa-avatar-background: transparent; 10 | --pa-avatar-foreground: transparent; 11 | 12 | @mixin shared-styles; 13 | 14 | &__container { 15 | border-radius: var(--pa-avatar-radius); 16 | box-sizing: border-box; 17 | font-family: var(--pa-font-family); 18 | font-size: var(--pa-font-size-normal); 19 | font-weight: var(--pa-avatar-initials-weight); 20 | height: var(--pa-avatar-size); 21 | padding: var(--pa-avatar-padding); 22 | width: var(--pa-avatar-size); 23 | background-image: linear-gradient( 24 | var(--pa-stripe-angle), 25 | var(--pa-avatar-background) 25%, 26 | transparent 25%, 27 | transparent 50%, 28 | var(--pa-avatar-background) 50%, 29 | var(--pa-avatar-background) 75%, 30 | transparent 75%, 31 | transparent 100% 32 | ); 33 | background-size: var(--pa-stripe-size); 34 | background-color: transparent; 35 | border-width: var(--pa-avatar-border-width); 36 | border-style: dashed; 37 | border-color: var(--pa-avatar-background); 38 | } 39 | 40 | @each $variant in primary, secondary, tertiary { 41 | &--$(variant) &__container { 42 | --pa-avatar-background: var(--pa-color-$(variant)-brightest); 43 | --pa-avatar-foreground: var(--pa-color-$(variant)-darkest); 44 | } 45 | } 46 | 47 | &__image { 48 | border-radius: var(--pa-avatar-radius); 49 | box-sizing: border-box; 50 | max-width: calc(100% + var(--pa-avatar-padding) * 2); 51 | max-height: calc(100% + var(--pa-avatar-padding) * 2); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/elements/enterprise/itchio/itchio.service.ts: -------------------------------------------------------------------------------- 1 | import { getWindow } from 'ssr-window'; 2 | import { classesToString, debug, Itch } from '~/helpers'; 3 | import type { ItchioGameInfo } from './itchio.model'; 4 | 5 | class ItchioService { 6 | public getClasses(className: string) { 7 | const base = classesToString(['pa-itchio', className || '']); 8 | 9 | return { base }; 10 | } 11 | 12 | public async getGameData(user: string, game: string, secret: string): Promise { 13 | debug(`ItchioService getGameData: user: ${user}, game: ${game}`); 14 | 15 | return new Promise((resolve) => { 16 | Itch.getGameData({ 17 | user: user, 18 | game: game, 19 | secret: secret, 20 | onComplete: (data) => { 21 | debug(`ItchioService getGameData onComplete: data: ${JSON.stringify(data)}`); 22 | resolve(data); 23 | } 24 | }); 25 | }); 26 | } 27 | 28 | public async processInfo(user: string, game: string, secret: string) { 29 | const data = await this.getGameData(user, game, secret); 30 | 31 | return data; 32 | } 33 | 34 | public onClickAction(user: string, game: string, width = 800, height = 600) { 35 | const window = getWindow(); 36 | 37 | const domain = 'itch.io'; 38 | const top = (screen.height - height) / 2; 39 | const left = (screen.width - width) / 2; 40 | 41 | debug(`ItchioService onClickAction: user: ${user}, game: ${game}, top: ${top}, left: ${left}`); 42 | const openedWindow = window.open( 43 | 'https://' + user + '.' + domain + '/' + game + '/purchase?popup=1', 44 | 'purchase', 45 | 'scrollbars=1, resizable=no, width=' + width + ', height=' + height + ', top=' + top + ', left=' + left 46 | ); 47 | 48 | if (typeof openedWindow.focus === 'function') { 49 | openedWindow.focus(); 50 | } 51 | } 52 | } 53 | 54 | export const itchioService = new ItchioService(); 55 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-vue.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | import { generateCodeSandboxLink } from './codesandbox.helper'; 3 | 4 | export function generateVueCodeSandboxLink(options) { 5 | const { components, extensions, code, dependencies } = options; 6 | const html = `
`; 7 | 8 | const previewCode = ` 10 | 11 | 22 | 23 | `; 24 | 25 | const demoCode = ` 26 | import { createApp } from 'vue'; 27 | import App from './App.vue'; 28 | import './index.css'; 29 | 30 | createApp(App).mount('#app') 31 | `.trim(); 32 | 33 | const extraFiles = { 34 | 'App.vue': { 35 | content: `${previewCode} 36 | ` 38 | } 39 | }; 40 | 41 | const projectDependencies = { 42 | ...dependencies, 43 | vue: '^3.2.33', 44 | '@papanasi/vue': `${lernaJson.version}` 45 | }; 46 | 47 | const devDependencies = { 48 | '@vue/cli-plugin-babel': '~4.5.0', 49 | '@vue/cli-plugin-eslint': '~4.5.0', 50 | '@vue/cli-service': '~4.5.0', 51 | '@vue/compiler-sfc': '^3.0.0-0' 52 | }; 53 | 54 | const packageJson = { 55 | scripts: { 56 | serve: 'vue-cli-service serve' 57 | }, 58 | babel: { 59 | presets: ['@vue/cli-plugin-babel/preset'] 60 | } 61 | }; 62 | 63 | const { url } = generateCodeSandboxLink({ 64 | html, 65 | demoCode, 66 | dependencies: projectDependencies, 67 | devDependencies, 68 | packageJson, 69 | publicFolder: 'public/', 70 | extraFiles 71 | }); 72 | 73 | return { url, content: previewCode }; 74 | } 75 | -------------------------------------------------------------------------------- /compiler/platforms/angular.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import htmlTags from 'html-tags'; 3 | import compiler from '../base.compiler.js'; 4 | 5 | const DEFAULT_OPTIONS = { 6 | target: 'angular', 7 | extension: 'ts', 8 | state: '', 9 | styles: '' 10 | }; 11 | 12 | (async () => { 13 | function customReplace(props) { 14 | const { file, outFile } = props; 15 | 16 | const data = fs.readFileSync(outFile, 'utf8'); 17 | const result = data 18 | // Add selector to be a directive because in angular you cannot use existing tags 19 | .replace( 20 | /selector: ?["|'](.+), (.*)["|']/, 21 | `selector: "${ 22 | !htmlTags.includes(file.name.replace('.lite', '')) ? '$1,' : '' 23 | }[pa-$1], $2", exportAs: "pa-$1", encapsulation: 2` 24 | ) 25 | // Enable as default 26 | .replace(/export class/, 'export default class') 27 | // Replace classname for class 28 | .replace(/\.className/g, '.class') 29 | .replace(/className(\:|\")/g, 'class$1') 30 | // Enable children 31 | .replace(/(,\n)?(\} from \"\@angular\/core\"\;)/, ', ContentChildren, QueryList $2') 32 | .replace( 33 | /\@Input\(\) className\: any\;/, 34 | "@Input() className: any;\n@ContentChildren('child') children: QueryList;" 35 | ) 36 | // Fix value names on selectors 37 | .replace(/='value\((.*, ?)'(.*)'\)'/g, '="value($1\'$2\')"') 38 | // Fix angular styles property 39 | .replace(/\[style\]/g, '[ngStyle]') 40 | // Remove keys in loops 41 | .replace(/\[key\]=".*"/g, '') 42 | // Add Optional chaining to nativeElement 43 | .replace(/\.nativeElement/g, '?.nativeElement') 44 | // TODO: Temporal meanwhile we find another why but this is stable 45 | .replace(/getData\(\);/g, 'getData.bind(this)();'); 46 | 47 | fs.writeFileSync(outFile, result, 'utf8'); 48 | } 49 | 50 | await compiler.compile({ ...DEFAULT_OPTIONS, customReplace }); 51 | })(); 52 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-svelte.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | import { generateCodeSandboxLink } from './codesandbox.helper'; 3 | 4 | export function generateSvelteCodeSandboxLink(options) { 5 | const { components, extensions, code, dependencies } = options; 6 | 7 | const html = `
`; 8 | 9 | const previewCode = ` 16 | ${code} 17 | `; 18 | 19 | const demoCode = `import App from "./App.svelte"; 20 | 21 | const app = new App({ 22 | target: document.querySelector("#app") 23 | }); 24 | 25 | export default app; 26 | `.trim(); 27 | 28 | const extraFiles = { 29 | 'App.svelte': { 30 | content: previewCode 31 | } 32 | }; 33 | 34 | const projectDependencies = { 35 | ...dependencies, 36 | svelte: '^3.32.3', 37 | '@papanasi/svelte': `${lernaJson.version}` 38 | }; 39 | 40 | const devDependencies = { 41 | 'npm-run-all': '^4.1.5', 42 | rollup: '^1.10.1', 43 | 'rollup-plugin-commonjs': '^9.3.4', 44 | 'rollup-plugin-node-resolve': '^4.2.3', 45 | 'rollup-plugin-svelte': '^6.1.1', 46 | 'rollup-plugin-terser': '^4.0.4', 47 | 'sirv-cli': '^0.3.1' 48 | }; 49 | 50 | const packageJson = { 51 | scripts: { 52 | autobuild: 'rollup -c -w', 53 | dev: 'run-p start:dev autobuild', 54 | start: 'sirv public', 55 | 'start:dev': 'sirv public --dev' 56 | } 57 | }; 58 | 59 | const { url } = generateCodeSandboxLink({ 60 | html, 61 | demoCode, 62 | dependencies: projectDependencies, 63 | devDependencies, 64 | packageJson, 65 | publicFolder: 'public/', 66 | extraFiles 67 | }); 68 | 69 | return { url, content: previewCode }; 70 | } 71 | -------------------------------------------------------------------------------- /compiler/platforms/svelte.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import glob from 'glob'; 3 | import compiler from '../base.compiler.js'; 4 | 5 | const DEFAULT_OPTIONS = { 6 | target: 'svelte', 7 | extension: 'svelte', 8 | state: '', 9 | styles: 'variables' 10 | }; 11 | 12 | (async () => { 13 | function customReplace(props) { 14 | const { outFile, outPath, isFirstCompilation } = props; 15 | 16 | if (isFirstCompilation) { 17 | const data = fs.readFileSync(`${outPath}/src/index.ts`, 'utf8'); 18 | const result = data 19 | // Add .svelte to index 20 | .replace(/(export)(.*)\/(.+)';/g, "$1$2/$3/$3.svelte';") 21 | .replace(/(extensions)\/(.*)\/(.*)\.svelte/g, '$1/$2') 22 | .replace(/\/helpers\.svelte/g, ''); 23 | 24 | fs.writeFileSync(`${outPath}/src/index.ts`, result, 'utf8'); 25 | 26 | // Add .svelte to all the indexes in src folder 27 | glob.sync(`${outPath}/src/elements/**/index.ts`).map((src) => { 28 | const data = fs 29 | .readFileSync(src, 'utf8') 30 | // add svelte to index 31 | .replace(/(export { default } from)(.*)(';)/g, '$1$2.svelte$3') 32 | // but remove from hooks 33 | .replace(/\.hook\.svelte/g, '.hook'); 34 | 35 | fs.writeFileSync(src, data, 'utf8'); 36 | }); 37 | } 38 | 39 | const data = fs.readFileSync(outFile, 'utf8'); 40 | const result = data 41 | // Work with children (currently not working as expected) 42 | .replace(/children/g, '$$$slots') 43 | // Fix circle svg as component 44 | .replace(/state\./g, '') 45 | // Svelte compiler is not adding let to the state values 46 | .replace(/^ (\w*) = (.*)/gm, ' let $1 = $2') 47 | // Fix state in svelte 48 | .replace(/svelte:component\n.*this=\{circle\}/g, 'circle') 49 | // Remove Onchange 50 | .replace('import onChange from "on-change";', ''); 51 | 52 | fs.writeFileSync(outFile, result, 'utf8'); 53 | } 54 | 55 | await compiler.compile({ ...DEFAULT_OPTIONS, customReplace }); 56 | })(); 57 | -------------------------------------------------------------------------------- /src/elements/components/avatar/avatar.service.ts: -------------------------------------------------------------------------------- 1 | import { classesToString, debug, randomColor } from '~/helpers'; 2 | 3 | class AvatarService { 4 | public getClasses(variant: string, disabled: boolean, className: string) { 5 | const base = classesToString([ 6 | 'pa-avatar', 7 | [variant, `pa-avatar--${variant}`], 8 | [disabled, 'is-disabled'], 9 | className || '' 10 | ]); 11 | 12 | const container = classesToString(['pa-avatar__container', [variant, `pa-avatar--${variant}`]]); 13 | 14 | debug(`AvatarService getClasses: base: ${base}, container: ${container}`); 15 | return { base, container }; 16 | } 17 | 18 | public async getStyles(name: string, variant: string) { 19 | const container = await this.getColor(name, variant); 20 | 21 | debug(`AvatarService getStyles: container: ${JSON.stringify(container)}`); 22 | return { container }; 23 | } 24 | 25 | public getInitials(name: string) { 26 | // From: https://stackoverflow.com/a/63763497/3274609 27 | const initials = name 28 | .match(/(^\S\S?|\s\S)?/g) 29 | .map((v) => v.trim()) 30 | .join('') 31 | .match(/(^\S|\S$)?/g) 32 | .join('') 33 | .toLocaleUpperCase(); 34 | 35 | debug(`AvatarService getInitials: initials: ${initials}`); 36 | return initials; 37 | } 38 | 39 | public async getColor(name: string, variant: string) { 40 | if (variant) { 41 | debug(`AvatarService getColor: variant exist: ${variant}`); 42 | return {}; 43 | } 44 | 45 | const color = await randomColor(name); 46 | 47 | debug(`AvatarService getColor: color: ${JSON.stringify(color)}`); 48 | 49 | return { 50 | '--pa-avatar-foreground': color.foreground, 51 | '--pa-avatar-background': color.background 52 | }; 53 | } 54 | 55 | public getSource(url: string, unavatar: string) { 56 | const source = unavatar ? `https://unavatar.io/${unavatar}` : url; 57 | 58 | debug(`AvatarService getSource: source: ${source}`); 59 | return source; 60 | } 61 | } 62 | 63 | export const avatarService = new AvatarService(); 64 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox-web.helper.ts: -------------------------------------------------------------------------------- 1 | import lernaJson from '../../../lerna.json'; 2 | import { generateCodeSandboxLink } from './codesandbox.helper'; 3 | 4 | export function generateWebCodeSandboxLink(options) { 5 | const { components, extensions, code, dependencies } = options; 6 | 7 | const html = `
${code}
8 | 9 | `; 10 | 11 | const demoCode = ` 12 | import "@webcomponents/custom-elements/src/native-shim.js"; 13 | import "@webcomponents/custom-elements/custom-elements.min"; 14 | import "@papanasi/webcomponents/papanasi.css"; 15 | import './index.css'; 16 | 17 | /** Note: In web components the CSS selectors are different because the shadow DOM is used. 18 | * Instead of .pa-row.is-error you should use pa-row::part(pa-row is-error) 19 | */ 20 | 21 | import { ${components.join(', ')} ${components.length > 0 && extensions.length > 0 ? ', ' : ''}${extensions.join( 22 | ', ' 23 | )} } from '@papanasi/webcomponents'; 24 | 25 | 26 | ${[...extensions, ''].join('(); \n')} 27 | `.trim(); 28 | 29 | const previewCode = `// index.js 30 | import { ${components.join(', ')} ${components.length > 0 && extensions.length > 0 ? ', ' : ''}${extensions.join( 31 | ', ' 32 | )} } from '@papanasi/webcomponents'; 33 | import "@papanasi/webcomponents/papanasi.css"; 34 | ${[...extensions, ''].join('(); \n')} 35 | // index.html 36 | ${code} 37 | `; 38 | 39 | const projectDependencies = { 40 | ...dependencies, 41 | '@webcomponents/custom-elements': '1.5.0', 42 | '@papanasi/webcomponents': `${lernaJson.version}` 43 | }; 44 | 45 | const devDependencies = { 46 | '@babel/core': '7.2.0', 47 | typescript: '4.4.4', 48 | 'parcel-bundler': '^1.6.1' 49 | }; 50 | 51 | const packageJson = { 52 | scripts: { 53 | start: 'parcel index.html --open' 54 | } 55 | }; 56 | 57 | const { url } = generateCodeSandboxLink({ 58 | html, 59 | demoCode, 60 | dependencies: projectDependencies, 61 | devDependencies, 62 | packageJson 63 | }); 64 | 65 | return { url, content: previewCode }; 66 | } 67 | -------------------------------------------------------------------------------- /.storybook/helpers/codesandbox/codesandbox.helper.ts: -------------------------------------------------------------------------------- 1 | import LZString from 'lz-string'; 2 | 3 | export function toBase64(string: string) { 4 | return LZString.compressToBase64(string).replace(/\+/g, `-`).replace(/\//g, `_`).replace(/=+$/, ``); 5 | } 6 | 7 | export function generateCodeSandboxLink(options) { 8 | const { 9 | html, 10 | demoCode, 11 | dependencies, 12 | devDependencies, 13 | packageJson, 14 | isTypescript = false, 15 | extraFiles = null, 16 | publicFolder = '' 17 | } = options; 18 | 19 | const indexName = `index.${isTypescript ? 'ts' : 'js'}`; 20 | const indexHTMLFolder = `${publicFolder}index.html`; 21 | 22 | const css = ` 23 | * { 24 | box-sizing: border-box; 25 | } 26 | 27 | body { 28 | --pa-grid-gutter: 0.15rem; 29 | --pa-color-primary-normal: #017af0; 30 | 31 | font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; 32 | padding-top: 1rem; 33 | } 34 | 35 | .footer { 36 | font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; 37 | font-size: 0.8rem; 38 | justify-content: flex-end; 39 | margin-top: 1rem; 40 | text-align: right; 41 | } 42 | 43 | `; 44 | 45 | const content = ` 46 | import './index.css'; 47 | ${demoCode} 48 | `; 49 | 50 | const parameters = { 51 | files: { 52 | 'package.json': { 53 | content: { 54 | ...packageJson, 55 | dependencies, 56 | devDependencies 57 | } 58 | }, 59 | 'index.css': { 60 | content: css 61 | }, 62 | [indexName]: { 63 | content 64 | } 65 | } 66 | }; 67 | 68 | if (extraFiles) { 69 | parameters.files = { ...parameters.files, ...extraFiles }; 70 | } 71 | 72 | if (html) { 73 | parameters.files[indexHTMLFolder] = { 74 | content: `${html} 75 | 80 | ` 81 | }; 82 | } 83 | 84 | const urlParams = toBase64(JSON.stringify(parameters)); 85 | 86 | return { url: `https://codesandbox.io/api/v1/sandboxes/define?parameters=${urlParams}`, content: demoCode }; 87 | } 88 | -------------------------------------------------------------------------------- /compiler/platforms/qwik.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import compiler from '../base.compiler.js'; 3 | 4 | const DEFAULT_OPTIONS = { 5 | target: 'qwik', 6 | extension: 'tsx', 7 | state: 'useState', 8 | styles: 'style-tag' 9 | }; 10 | 11 | (async () => { 12 | function customReplace(props) { 13 | const { outFile, file } = props; 14 | 15 | const name = file.name.replace('.lite', ''); 16 | const pascalName = name.charAt(0).toUpperCase() + name.slice(1); 17 | 18 | const data = fs.readFileSync(outFile, 'utf8'); 19 | const result = data 20 | // Import types 21 | .replace(/import/, `import type { ${pascalName}Props } from './${name}.model';\nimport './${name}.css';\nimport`) 22 | // fix props on qwik 23 | .replace( 24 | /export const (.*) = component\$\(\((props)\) => \{/g, 25 | `export const ${pascalName} = component$((props: ${pascalName}Props) => {` 26 | ) 27 | // Fix https://github.com/BuilderIO/mitosis/pull/855 28 | // .replace(/useClientEffect/g, 'useMount') 29 | // Make all useTask async just in case 30 | .replace(/useTask\$\(\(/g, 'useTask$(async (') 31 | // Make all useMount to useTask async just in case 32 | .replace(/useMount\$\(\(/g, 'useTask$(async (') 33 | // Make all useWatch async just in case 34 | .replace(/useWatch\$\(\(/g, 'useWatch$(async (') 35 | // Then import useTask$, 36 | .replace(/useMount\$,/g, 'useTask$,') 37 | // Replace classname for class 38 | .replace(/\.className/g, '.class') 39 | // TODO: Temporal meanwhile we find another why but this is stable 40 | .replace(/getData\(\);/g, 'await getData();') 41 | // Signal needs to be typed 42 | .replace(/useSignal\(\)/g, 'useSignal()') 43 | .replace(/state.codeService = service;/g, 'state.codeService = noSerialize(service);') 44 | .replace(/} from "@builder.io\/qwik";/g, ', noSerialize} from "@builder.io/qwik";') 45 | .replace(/(import[\s\S]*,)([\s]*, noSerialize)/g, '$1 noSerialize'); 46 | 47 | fs.writeFileSync(outFile, result, 'utf8'); 48 | } 49 | 50 | await compiler.compile({ ...DEFAULT_OPTIONS, customReplace }); 51 | })(); 52 | -------------------------------------------------------------------------------- /packages/webcomponents/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@papanasi/webcomponents", 3 | "version": "1.1.2", 4 | "license": "MIT", 5 | "author": "ckgrafico/papanasi", 6 | "description": "Papanasi Web Components UI Library", 7 | "type": "module", 8 | "main": "./dist/papanasi-webcomponents.umd.js", 9 | "module": "./dist/papanasi-webcomponents.es.js", 10 | "types": "./dist/index.d.ts", 11 | "exports": { 12 | ".": { 13 | "import": "./dist/papanasi-webcomponents.es.js", 14 | "require": "./dist/papanasi-webcomponents.umd.js" 15 | }, 16 | "./papanasi.css": { 17 | "import": "./dist/themes/papanasi.css", 18 | "require": "./dist/themes/papanasi.css" 19 | }, 20 | "./sketch.css": { 21 | "import": "./dist/themes/sketch.css", 22 | "require": "./dist/themes/sketch.css" 23 | }, 24 | "./custom-elements.json": { 25 | "import": "./custom-elements.json", 26 | "require": "./custom-elements.json" 27 | } 28 | }, 29 | "dependencies": { 30 | "codejar": "^3.6.0", 31 | "copy-to-clipboard": "^3.3.2", 32 | "ssr-window": "^4.0.2" 33 | }, 34 | "files": [ 35 | "dist" 36 | ], 37 | "scripts": { 38 | "prebuild": "copyfiles ../../.themes/** ./dist/themes --flat", 39 | "build": "run-s build:**", 40 | "build:code": "rollup -c", 41 | "build:styles": "replace \"\\.pa-(.*?)((--|__).*?)?((\\.pa|\\.is|\\.has).*?)?(,|:|{)\" \"pa-$1::part(pa-$1$2 $4)$6\" ./dist -r --include=\"*.es.js,*.umd.js,*.css\" --silent", 42 | "build:styles-classes-css": "replace \" \\.(pa-|is-|has-)(.*?)(,|:|{)\" \" $1$2$3\" ./dist -r --include=\"*.css\" --silent", 43 | "build:styles-classes-states": "replace \"(::part\\(.*?)\\.(pa-|is-|has-)(.*?)(\\))\" \"$1 $2$3$4\" ./dist -r --include=\"*.css\" --silent", 44 | "build:styles-classes-js": "replace \" \\.(pa-|is-|has-)(.*?)(,|:|{)\" \" $1$2$3\" ./dist -r --include=\"*.es.js,*.umd.js\" --silent", 45 | "build:schema": "custom-elements-manifest analyze", 46 | "postbuild": "renamer --find papanasi-webcomponents.es.d.ts --replace index.d.ts ./dist/* --silent && rimraf ./dist/papanasi-webcomponents.umd.d.ts" 47 | }, 48 | "publishConfig": { 49 | "access": "public" 50 | }, 51 | "gitHead": "f2eefa7b93814a19363b851fc037688813bc9ed8" 52 | } 53 | -------------------------------------------------------------------------------- /src/elements/enterprise/itchio/itchio.lite.tsx: -------------------------------------------------------------------------------- 1 | import { onInit, Show, useMetadata, useStore } from '@builder.io/mitosis'; 2 | import { debug } from '~/helpers'; 3 | import './itchio.css'; 4 | import type { ItchioProps, ItchioState } from './itchio.model'; 5 | import { itchioService } from './itchio.service'; 6 | 7 | useMetadata({ isAttachedToShadowDom: true }); 8 | 9 | export default function Itchio(props: ItchioProps) { 10 | const state = useStore({ 11 | loaded: false, 12 | get classes() { 13 | return itchioService.getClasses(props.className); 14 | }, 15 | gameInfo: null, 16 | onClickAction(user: string, game: string, width: number, height: number) { 17 | itchioService.onClickAction(user, game, width, height); 18 | } 19 | }); 20 | 21 | onInit(() => { 22 | async function getData() { 23 | const data = await itchioService.processInfo(props.user, props.game, props.secret); 24 | 25 | state.gameInfo = data; 26 | state.loaded = true; 27 | 28 | debug('ItchioService callback processed info'); 29 | props.onLoad && props.onLoad(data); 30 | } 31 | 32 | getData(); 33 | }); 34 | 35 | return ( 36 |
37 |
38 | 39 | {state.gameInfo.title} 40 | 41 |
42 | 43 |
44 | {state.gameInfo.title} 45 | {state.gameInfo.price} 46 |
47 |
48 | 49 | state.onClickAction(props.user, props.game, props.width, props.height)} 52 | > 53 | 54 | {props.children} 55 | 56 | 57 | 58 | {props.slotLoading} 59 | 60 | 61 |
62 |
63 |
64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /src/helpers/breakpoint.helper.ts: -------------------------------------------------------------------------------- 1 | import { getDocument, getWindow } from 'ssr-window'; 2 | import { Breakpoint, breakpoints } from '../models'; 3 | import { wait } from './wait.helper'; 4 | 5 | export function getBreakpointClasses( 6 | basic: string | number, 7 | xxs: string | number, 8 | xs: string | number, 9 | s: string | number, 10 | m: string | number, 11 | l: string | number, 12 | xl: string | number, 13 | xxl: string | number, 14 | prefix = '' 15 | ) { 16 | const props: { [key: string]: string | number } = { basic, xxs, xs, s, m, l, xl, xxl }; 17 | 18 | const usedBreakpoints = Object.entries(props) 19 | .filter(([key]: [Breakpoint, string]) => breakpoints.find((x) => x.value === key)) 20 | .filter((x) => x[0] && x[1] !== '' && x[1] !== null && x[1] !== undefined); 21 | 22 | const breakpointsClasses = usedBreakpoints.map(([key, value]: [Breakpoint, string]) => prefix + value + '@' + key); 23 | 24 | return ' ' + breakpointsClasses.join(' '); 25 | } 26 | 27 | /* We are using this because nowadays you cannot have a custom property in a media query */ 28 | 29 | function checkBreakpoints() { 30 | const window = getWindow(); 31 | const document = getDocument(); 32 | 33 | const styles = window.getComputedStyle(document.documentElement); 34 | const medias = breakpoints.map((breakpoint) => ({ 35 | key: breakpoint.value, 36 | value: 37 | breakpoint.value === Breakpoint.Basic 38 | ? '0' 39 | : styles.getPropertyValue(`--pa-breakpoint-${breakpoint.value}`).trim() 40 | })); 41 | 42 | if (!window.matchMedia || !document.body || !document.body.classList) { 43 | return; 44 | } 45 | 46 | function onChangeMedia(media, matches) { 47 | const className = `breakpoint-${media.trim()}`; 48 | 49 | if (matches) { 50 | document.body.classList.add(className); 51 | } else { 52 | document.body.classList.remove(className); 53 | } 54 | } 55 | 56 | medias.forEach(({ key, value }) => { 57 | onChangeMedia(key, window.innerWidth > Number(value.replace('px', ''))); 58 | window.matchMedia(`(min-width: ${value})`).addEventListener('change', (e) => onChangeMedia(key, e.matches)); 59 | }); 60 | } 61 | 62 | export async function initBreakpointChecker() { 63 | await wait(); 64 | checkBreakpoints(); 65 | } 66 | -------------------------------------------------------------------------------- /compiler/dev.tasks.js: -------------------------------------------------------------------------------- 1 | import chokidar from 'chokidar'; 2 | import { Listr } from 'listr2'; 3 | import ora from 'ora'; 4 | import path from 'path'; 5 | 6 | (async () => { 7 | const execa = (await import('execa')).command; 8 | 9 | const tasks = new Listr([ 10 | { 11 | title: 'Clean output', 12 | task: () => 13 | execa('yarn clean').catch(() => { 14 | throw new Error('Cannot remove output directory'); 15 | }) 16 | }, 17 | { 18 | title: 'Compile Themes', 19 | task: () => 20 | execa('yarn themes').catch((error) => { 21 | throw new Error('Error compiling Themes' + error); 22 | }) 23 | }, 24 | { 25 | title: 'Compile React Components', 26 | task: () => 27 | execa('node ./compiler/platforms/react').catch((error) => { 28 | throw new Error('Error compiling React' + error); 29 | }) 30 | }, 31 | { 32 | title: 'Bundle React', 33 | task: () => 34 | execa('yarn lerna --verbose --scope=@papanasi/react build').catch((error) => { 35 | throw new Error('Error bundling React ' + error); 36 | }) 37 | }, 38 | { 39 | title: 'Launch Watcher', 40 | task: async (ctx, task) => { 41 | task.title = 'Watching for changes'; 42 | 43 | return chokidar.watch(['src/**/*']).on('all', async (event, pathName) => { 44 | if (event !== 'change') { 45 | return; 46 | } 47 | 48 | const file = path.parse(pathName); 49 | const name = file.dir.replace('src\\', ''); 50 | const spinner = ora(`Changed ${name}, compiling... `).start(); 51 | 52 | try { 53 | await execa('node ./compiler/platforms/react --dev'); 54 | await execa('yarn lerna --verbose --scope=@papanasi/react build'); 55 | } catch (e) { 56 | spinner.text = `Error compiling ${e.message}.`; 57 | spinner.fail(); 58 | 59 | return; 60 | } 61 | 62 | spinner.text = 'Compiled successfully.'; 63 | spinner.succeed(); 64 | }); 65 | }, 66 | options: { 67 | persistentOutput: true 68 | } 69 | } 70 | ]); 71 | 72 | tasks.run().catch((err) => { 73 | console.error(err); 74 | }); 75 | })(); 76 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Papanasi 2 | 3 | Thank you for considering contributing to this open source components library! To have this kind of people in the community is awesome. 4 | Reading and following these guidelines will help us make the contribution process easy and effective for everyone involved. 5 | 6 | ## Code of Conduct 7 | 8 | Open source community is important to us, thats why everybody involved in any intereaction should do the best posible and understand that others are doing too. 9 | By contributing to this project, you agree to uphold our [Code of Conduct](https://github.com/ckgrafico/papanasi/blob/master/CODE-OF-CONDUCT.md). 10 | 11 | ## Helping with the repo 12 | If you want to help us contributing with some code, there are some ways to do it. 13 | 14 | ### Solving issues 15 | There are some issues highlighted as `help wanted` that can be interesting to start to contribute in this project, some of them are `bugs` or `enhancements` that are required to improve the quality of this repository, you can filter all of them in the [issues page](https://github.com/CKGrafico/papanasi/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). 16 | 17 | ### Suggesting ideas 18 | Anybody can suggest new components to be added to the repo, just create a [new issue](https://github.com/CKGrafico/papanasi/issues/new), all the ideas are welcome :) 19 | 20 | ### Creating components 21 | Right now we have three kind of components that kind inspire you to add new components to this project (or create one that is in the issues). 22 | - **Regular component**: The best example is the [Button](https://papanasi.js.org/?path=/docs/components-button--default-story) component, a regular component is a component that has all the logic managed by itslef and has no dependencies, some examples in any library can be a `button`, `pill`, `switch`, `loading`, etc. 23 | - **Wrapper component**: A good example can be the [Code](https://papanasi.js.org/?path=/docs/components-code--default-story) component, this kind of components are wrapping vanilla JavaScript libraries and converting them to universal components, like `select`, `table`, `virtual-scroll`, etc. 24 | - **Layout component**: There are not a lot like this, but [Column](https://papanasi.js.org/?path=/docs/layout-column--default-story) component, is the example that can represent them better, are useful to improve the layout. 25 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/pill.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-pill { 4 | @mixin shared-styles; 5 | 6 | --pa-pill-radius: 10rem; 7 | --pa-pill-font-weight: var(--pa-font-weight-medium); 8 | 9 | background-image: linear-gradient( 10 | var(--pa-stripe-angle), 11 | var(--pa-color-$(variant)-dark) 25%, 12 | var(--pa-color-$(variant)-normal) 25%, 13 | var(--pa-color-$(variant)-normal) 50%, 14 | var(--pa-color-$(variant)-dark) 50%, 15 | var(--pa-color-$(variant)-dark) 75%, 16 | var(--pa-color-$(variant)-normal) 75%, 17 | var(--pa-color-$(variant)-normal) 100% 18 | ); 19 | background-color: var(--pa-color-basic-brightest); 20 | border-color: var(--pa-color-basic-bright); 21 | border-radius: var(--pa-pill-radius); 22 | color: var(--pa-color-basic-darker); 23 | font-family: var(--pa-font-family); 24 | font-weight: var(--pa-pill-font-weight); 25 | transition-duration: var(--pa-transition-duration-normal); 26 | transition-property: var(--pa-transition-colors); 27 | background-size: var(--pa-stripe-size); 28 | 29 | @each $variant in primary, secondary, tertiary { 30 | &--$(variant) { 31 | background-image: linear-gradient( 32 | var(--pa-stripe-angle), 33 | var(--pa-color-$(variant)-dark) 25%, 34 | var(--pa-color-$(variant)-normal) 25%, 35 | var(--pa-color-$(variant)-normal) 50%, 36 | var(--pa-color-$(variant)-dark) 50%, 37 | var(--pa-color-$(variant)-dark) 75%, 38 | var(--pa-color-$(variant)-normal) 75%, 39 | var(--pa-color-$(variant)-normal) 100% 40 | ); 41 | background-color: var(--pa-color-$(variant)-normal); 42 | border-color: transparent; 43 | color: var(--pa-color-basic-brightest); 44 | } 45 | } 46 | 47 | @each $intent in info, success, warning, error { 48 | &.is-$(intent) { 49 | background-image: linear-gradient( 50 | var(--pa-stripe-angle), 51 | var(--pa-color-$(intent)-brighter) 25%, 52 | var(--pa-color-$(intent)-bright) 25%, 53 | var(--pa-color-$(intent)-bright) 50%, 54 | var(--pa-color-$(intent)-brighter) 50%, 55 | var(--pa-color-$(intent)-brighter) 75%, 56 | var(--pa-color-$(intent)-bright) 75%, 57 | var(--pa-color-$(intent)-bright) 100% 58 | ); 59 | background-color: var(--pa-color-$(intent)-bright); 60 | color: var(--pa-color-$(intent)-darker); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/spinner.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-spinner { 4 | --pa-spinner-linecap: round; 5 | --pa-spinner-stroke: 6; 6 | --pa-spinner-offset: 200; 7 | --pa-spinner-duration: 4s; 8 | 9 | @mixin shared-styles; 10 | 11 | &--full, 12 | &--fullscreen { 13 | @mixin background-opacity var(--pa-color-basic-brightest), 0.2; 14 | backdrop-filter: blur(3px); 15 | z-index: var(--pa-zindex-max); 16 | } 17 | 18 | &__icon { 19 | animation: rotator270 var(--pa-spinner-duration) linear infinite; 20 | } 21 | 22 | &__path { 23 | animation: dash var(--pa-spinner-duration) ease-in-out infinite, 24 | colors calc(var(--pa-spinner-duration) * 4) ease-in-out infinite; 25 | stroke-dasharray: var(--pa-spinner-offset); 26 | stroke-linecap: var(--pa-spinner-linecap); 27 | stroke-width: var(--pa-spinner-stroke); 28 | } 29 | 30 | @keyframes colors { 31 | 0% { 32 | stroke: var(--pa-color-basic-dark); 33 | } 34 | 35 | 50% { 36 | stroke: var(--pa-color-basic-darker); 37 | } 38 | 39 | 100% { 40 | stroke: var(--pa-color-basic-dark); 41 | } 42 | } 43 | 44 | @each $variant in primary, secondary, tertiary { 45 | &--$(variant) &--full, 46 | &--$(variant) &--fullscreen { 47 | @mixin background-opacity var(--pa-color-$(variant)-brightest), 0.2; 48 | } 49 | 50 | &--$(variant) &__path { 51 | animation: dash var(--pa-spinner-duration) ease-in-out infinite, 52 | colors-$(variant) calc(var(--pa-spinner-duration) * 4) ease-in-out infinite; 53 | 54 | @keyframes colors-$(variant) { 55 | 0% { 56 | stroke: var(--pa-color-$(variant)-normal); 57 | } 58 | 59 | 50% { 60 | stroke: var(--pa-color-$(variant)-darker); 61 | } 62 | 63 | 100% { 64 | stroke: var(--pa-color-$(variant)-normal); 65 | } 66 | } 67 | } 68 | } 69 | 70 | @keyframes rotator270 { 71 | 0% { 72 | transform: rotate(0deg); 73 | } 74 | 75 | 100% { 76 | transform: rotate(270deg); 77 | } 78 | } 79 | 80 | @keyframes dash { 81 | 0% { 82 | stroke-dashoffset: var(--pa-spinner-offset); 83 | } 84 | 50% { 85 | stroke-dashoffset: var(--pa-spinner-offset) / 4; 86 | transform: rotate(135deg); 87 | } 88 | 100% { 89 | stroke-dashoffset: var(--pa-spinner-offset); 90 | transform: rotate(450deg); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/styles/themes/sketch/spinner.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-spinner { 4 | --pa-spinner-linecap: square; 5 | --pa-spinner-stroke: 4; 6 | --pa-spinner-offset: 16; 7 | --pa-spinner-duration: 6s; 8 | 9 | @mixin shared-styles; 10 | 11 | &--full, 12 | &--fullscreen { 13 | @mixin background-opacity var(--pa-color-basic-brightest), 0.2; 14 | backdrop-filter: blur(1px); 15 | z-index: var(--pa-zindex-max); 16 | } 17 | 18 | &__icon { 19 | animation: rotator270 var(--pa-spinner-duration) linear infinite; 20 | } 21 | 22 | &__path { 23 | animation: dash var(--pa-spinner-duration) ease-in-out infinite, 24 | colors calc(var(--pa-spinner-duration) * 4) ease-in-out infinite; 25 | stroke-dasharray: var(--pa-spinner-offset); 26 | stroke-linecap: var(--pa-spinner-linecap); 27 | stroke-width: var(--pa-spinner-stroke); 28 | } 29 | 30 | @keyframes colors { 31 | 0% { 32 | stroke: var(--pa-color-basic-dark); 33 | } 34 | 35 | 50% { 36 | stroke: var(--pa-color-basic-darker); 37 | } 38 | 39 | 100% { 40 | stroke: var(--pa-color-basic-dark); 41 | } 42 | } 43 | 44 | @each $variant in primary, secondary, tertiary { 45 | &--$(variant) &--full, 46 | &--$(variant) &--fullscreen { 47 | @mixin background-opacity var(--pa-color-$(variant)-brightest), 0.2; 48 | } 49 | 50 | &--$(variant) &__path { 51 | animation: dash var(--pa-spinner-duration) ease-in-out infinite, 52 | colors-$(variant) calc(var(--pa-spinner-duration) * 4) ease-in-out infinite; 53 | 54 | @keyframes colors-$(variant) { 55 | 0% { 56 | stroke: var(--pa-color-$(variant)-normal); 57 | } 58 | 59 | 50% { 60 | stroke: var(--pa-color-$(variant)-darker); 61 | } 62 | 63 | 100% { 64 | stroke: var(--pa-color-$(variant)-normal); 65 | } 66 | } 67 | } 68 | } 69 | 70 | @keyframes rotator270 { 71 | 0% { 72 | transform: rotate(0deg); 73 | } 74 | 75 | 100% { 76 | transform: rotate(270deg); 77 | } 78 | } 79 | 80 | @keyframes dash { 81 | 0% { 82 | stroke-dashoffset: var(--pa-spinner-offset); 83 | } 84 | 50% { 85 | stroke-dashoffset: var(--pa-spinner-offset) / 4; 86 | transform: rotate(135deg); 87 | } 88 | 100% { 89 | stroke-dashoffset: var(--pa-spinner-offset); 90 | transform: rotate(450deg); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /.storybook/components/Codesandbox.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Code } from '../../packages/react/src'; 3 | import { 4 | generateAngularCodeSandboxLink, 5 | generatePreactCodeSandboxLink, 6 | generateQwikCodeSandboxLink, 7 | generateReactCodeSandboxLink, 8 | generateSolidCodeSandboxLink, 9 | generateSvelteCodeSandboxLink, 10 | generateVueCodeSandboxLink, 11 | generateWebCodeSandboxLink 12 | } from '../helpers'; 13 | 14 | enum CodesandboxPlatform { 15 | Angular = 'angular', 16 | Preact = 'preact', 17 | Qwik = 'qwik', 18 | React = 'react', 19 | Solid = 'solid', 20 | Svelte = 'svelte', 21 | Vue = 'vue', 22 | WebComponents = 'webcomponents' 23 | } 24 | 25 | type CodesandboxProps = { 26 | components: string[]; 27 | extensions: string[]; 28 | code: string; 29 | platform: CodesandboxPlatform; 30 | dependencies?: { [key: string]: string }; 31 | }; 32 | 33 | const generators = { 34 | [CodesandboxPlatform.Angular]: generateAngularCodeSandboxLink, 35 | [CodesandboxPlatform.Preact]: generatePreactCodeSandboxLink, 36 | [CodesandboxPlatform.Qwik]: generateQwikCodeSandboxLink, 37 | [CodesandboxPlatform.React]: generateReactCodeSandboxLink, 38 | [CodesandboxPlatform.Solid]: generateSolidCodeSandboxLink, 39 | [CodesandboxPlatform.Svelte]: generateSvelteCodeSandboxLink, 40 | [CodesandboxPlatform.Vue]: generateVueCodeSandboxLink, 41 | [CodesandboxPlatform.WebComponents]: generateWebCodeSandboxLink 42 | }; 43 | 44 | const icons = { 45 | [CodesandboxPlatform.Angular]: 'angular-icon', 46 | [CodesandboxPlatform.Preact]: 'preact', 47 | [CodesandboxPlatform.Qwik]: 'qwik', 48 | [CodesandboxPlatform.React]: 'react', 49 | [CodesandboxPlatform.Solid]: 'solidjs-icon', 50 | [CodesandboxPlatform.Svelte]: 'svelte-icon', 51 | [CodesandboxPlatform.Vue]: 'vue', 52 | [CodesandboxPlatform.WebComponents]: 'w3c' 53 | }; 54 | 55 | export function Codesandbox(props: CodesandboxProps) { 56 | const { components = [], extensions = [], code, platform, dependencies = {} } = props; 57 | 58 | const { url, content } = generators[platform]({ components, extensions, code, dependencies }); 59 | const iconPlatform = icons[platform]; 60 | const icon = `https://raw.githubusercontent.com/gilbarbara/logos/master/logos/${iconPlatform}.svg`; 61 | 62 | return ( 63 |
64 | x)} 79 | /> 80 |
81 | ); 82 | } 83 | -------------------------------------------------------------------------------- /src/elements/components/breadcrumb/breadcrumb.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs'; 2 | import { Breadcrumb } from '../../../../packages/react/src'; 3 | import { Codesandbox } from '../../../../.storybook/components'; 4 | 5 | 17 | 18 | export const Template = (args) => ( 19 | 27 | ); 28 | 29 | # Breadcrumb 30 | 31 | Breadcrumbs display the current location within a hierarchy and allow navigation. 32 | 33 | ## Showcase 34 | 35 | 36 | 37 | {Template.bind({})} 38 | 39 | 40 | 41 | ### Properties 42 | 43 | 44 | 45 | ## How to use this component 46 | 47 | ### Angular 48 | 49 | `} 53 | /> 54 | 55 | ### Preact 56 | 57 | `} 61 | /> 62 | 63 | ### Qwik 64 | 65 | `} 69 | /> 70 | 71 | ### React 72 | 73 | `} 77 | /> 78 | 79 | ### Solid 80 | 81 | `} 85 | /> 86 | 87 | ### Svelte 88 | 89 | `} 93 | /> 94 | 95 | ### Vue 96 | 97 | `} 101 | /> 102 | 103 | ### Web Components 104 | 105 | `} /> 106 | -------------------------------------------------------------------------------- /src/elements/layout/column/grid.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs'; 2 | import { Column, Container, Row } from '../../../../packages/react/src'; 3 | import { variants, Intent, intents } from '../../../models'; 4 | import { getBreakpointArgTypes } from '../../../helpers'; 5 | import { Customization } from '../../../../.storybook/components'; 6 | 7 | 45 | 46 | export const Template = (args) => { 47 | const { fluid, direction, ...column } = args; 48 | return ( 49 | 50 | 51 | Row 1 of 3 - Column 1 of 3 52 | Row 1 of 3 - Column 2 of 3 53 | Row 1 of 3 - Column 3 of 3 54 | 55 | 56 | Row 2 of 3 - Column 1 of 3 57 | Row 2 of 3 - Column 2 of 3 58 | Row 2 of 3 - Column 3 of 3 59 | 60 | 61 | Row 3 of 3 - Column 1 of 3 62 | Row 3 of 3 - Column 2 of 3 63 | Row 3 of 3 - Column 3 of 3 64 | 65 | 66 | ); 67 | }; 68 | 69 | # Grid 70 | 71 | Grids are not components itslef but the association between `Containers`, `Rows` and `Columns`. Are useful to create simple layouts for your pages. 72 | 73 | ## Showcase 74 | 75 | 76 | 77 | {Template.bind({})} 78 | 79 | 80 | 81 | ### Customization 82 | 83 | 92 | 93 | ### Properties 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/elements/extensions/toast/toast.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs'; 2 | import { Customization, Codesandbox } from '../../../../.storybook/components'; 3 | import { Toast, useToastExtension } from '../../../../packages/react/src'; 4 | 5 | 16 | 17 | export const Template = (args) => ( 18 |
19 | {(() => { 20 | window.toast = useToastExtension(); 21 | return ''; 22 | })()} 23 |
24 | 25 | { 27 | // toast.success({ message: 'example' }) 28 | window.toast.success({ message: 'example' + Math.random() }); 29 | }} 30 | > 31 | Click me 32 | 33 |
34 |
35 | ); 36 | 37 | # Toast 38 | 39 | TODO 40 | 41 | ## Showcase 42 | 43 | 44 | 50 | {Template.bind({})} 51 | 52 | 53 | 54 | ### Customization 55 | 56 | 57 | 58 | ### Properties 59 | 60 | 61 | 62 | ## How to use this extension 63 | 64 | ### Angular 65 | 66 | Hover me`} 71 | /> 72 | 73 | ### Preact 74 | 75 | Hover me`} 80 | /> 81 | 82 | ### Qwik 83 | 84 | Hover me`} 89 | /> 90 | 91 | ### React 92 | 93 | Hover me`} 98 | /> 99 | 100 | ### Solid 101 | 102 | Hover me`} 107 | /> 108 | 109 | ### Svelte 110 | 111 | Hover me`} 116 | /> 117 | 118 | ### Vue 119 | 120 | Hover me`} 125 | /> 126 | 127 | ### Web Components 128 | 129 | Hover me`} 133 | /> 134 | -------------------------------------------------------------------------------- /src/styles/themes/papanasi/button.css: -------------------------------------------------------------------------------- 1 | @import '../../build.css'; 2 | 3 | .pa-button { 4 | @mixin shared-styles; 5 | 6 | --pa-button-radius: var(--pa-border-radius-small); 7 | --pa-button-border-width: var(--pa-border-width-small); 8 | --pa-button-font-weight: var(--pa-font-weight-medium); 9 | --pa-button-outline: var(--pa-outline-width); 10 | 11 | background-color: var(--pa-color-basic-brightest); 12 | border-color: var(--pa-color-basic-bright); 13 | border-radius: var(--pa-button-radius); 14 | border-style: solid; 15 | border-width: var(--pa-button-border-width); 16 | color: var(--pa-color-basic-darker); 17 | font-family: var(--pa-font-family); 18 | font-weight: var(--pa-button-font-weight); 19 | outline: var(--pa-button-outline) solid transparent; 20 | transition-duration: var(--pa-transition-duration-normal); 21 | transition-property: var(--pa-transition-colors); 22 | 23 | &:hover { 24 | background-color: var(--pa-color-basic-brighter); 25 | border-color: var(--pa-color-basic-normal); 26 | } 27 | 28 | &:active, 29 | &:focus { 30 | outline-color: var(--pa-color-basic-brighter); 31 | } 32 | 33 | @each $variant in primary, secondary, tertiary { 34 | &--$(variant) { 35 | background-color: var(--pa-color-$(variant)-normal); 36 | border-color: transparent; 37 | color: var(--pa-color-basic-brightest); 38 | 39 | &:hover { 40 | background-color: var(--pa-color-$(variant)-dark); 41 | border-color: var(--pa-color-$(variant)-dark); 42 | } 43 | 44 | &:active, 45 | &:focus { 46 | outline-color: var(--pa-color-$(variant)-brighter); 47 | } 48 | } 49 | 50 | &--outline&--$(variant) { 51 | background-color: transparent; 52 | border-color: var(--pa-color-$(variant)-normal); 53 | color: var(--pa-color-$(variant)-dark); 54 | 55 | &:hover { 56 | background-color: var(--pa-color-$(variant)-brightest); 57 | border-color: var(--pa-color-$(variant)-dark); 58 | color: var(--pa-color-$(variant)-darker); 59 | } 60 | } 61 | } 62 | 63 | @each $intent in info, success, warning, error { 64 | &.is-$(intent) { 65 | background-color: var(--pa-color-$(intent)-bright); 66 | color: var(--pa-color-$(intent)-darkest); 67 | border-color: transparent; 68 | 69 | &:hover { 70 | background-color: var(--pa-color-$(intent)-normal); 71 | border-color: var(--pa-color-$(intent)-normal); 72 | } 73 | 74 | &:active, 75 | &:focus { 76 | outline-color: var(--pa-color-$(intent)-brighter); 77 | } 78 | } 79 | 80 | &--outline&.is-$(intent) { 81 | background-color: transparent; 82 | border-color: var(--pa-color-$(intent)-bright); 83 | color: var(--pa-color-$(intent)-normal); 84 | 85 | &:hover { 86 | background-color: var(--pa-color-$(intent)-brightest); 87 | border-color: var(--pa-color-$(intent)-normal); 88 | color: var(--pa-color-$(intent)-darker); 89 | } 90 | } 91 | } 92 | 93 | &.is-disabled { 94 | opacity: 0.75; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /docs/elements.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Canvas } from '@storybook/addon-docs'; 2 | import { Container, Row, Column, Button, Avatar, Itchio, useTooltipExtension } from '../packages/react/src'; 3 | import { Customization } from '../.storybook/components'; 4 | 5 | 6 | 7 | # Typology of Elements 8 | 9 | **Papanasi** has four different types of elements, that ones are: `layout`, `components`, `enterprise` and `extensions`. Each type has a **different purpose** and a different way of being used, explained in the next lines. 10 | 11 | ## Layout 12 | 13 | Those elements are made to **help the developer to create a basic layout** for any page, that kind of elements exist in all the UI Libraries that you can imagine, and they are the ones that you will use the most. 14 | 15 | What makes these from Papanasi different is that they are **fully customizable**. You can use them as they are, or you can customize them to fit your needs. 16 | 17 | Some examples are `Container`, `Row` and `Column`. 18 | 19 | 20 | 21 | 22 | Row 1 - Column 1 of 3 23 | Row 1 - Column 2 of 3 24 | Row 1 - Column 3 of 3 25 | 26 | 27 | Row 2 - Column 1 of 3 28 | Row 2 - Column 2 of 3 29 | Row 2 - Column 3 of 3 30 | 31 | 32 | Row 3 - Column 1 of 3 33 | Row 3 - Column 2 of 3 34 | Row 3 - Column 3 of 3 35 | 36 | 37 | 38 | 39 | ## Components 40 | 41 | Are the core of **Papanasi**, all the components should follow the [manifesto](https://github.com/CKGrafico/papanasi#-manifesto), should be also **customizable from global or scoped variables**. 42 | 43 | Most popular components are `Button` or `Avatar`: 44 | 45 | 46 | 47 | 50 | 51 | 52 | 53 | ## Enterprise 54 | 55 | Those elements are the ones that are **specific for a company or library**, and they are not part of the core of **Papanasi**. The main idea is to bring the opportunity to create components from **SDKs** or **APIs** writing the code just once. 56 | 57 | The first enterprise component was `Itchio`: 58 | 59 | 60 | 61 | Click me 62 | 63 | 64 | 65 | ## Extensions 66 | 67 | Papanasi extensions are **plugins** that can be used to extend our functionality. Those are not components are can be used as any other library. 68 | 69 | A good example of an extension is the `Tooltip`: 70 | 71 | 72 | {(() => { 73 | useTooltipExtension(document.body.querySelector('.tooltip-example')); 74 | return ''; 75 | })()} 76 |
77 | 78 | Hover me 79 | 80 |
81 |
82 | 83 |