('size'),
21 | };
22 | };
23 |
--------------------------------------------------------------------------------
/src/components/CloseButton/CloseButton.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import { browser } from 'protractor';
3 | import { waitForVisibilityOf, createStoryUrl } from 'wix-ui-test-utils/protractor';
4 | import { enumValues } from '../../utils';
5 | import { closeButtonTestkitFactory } from '../../testkit/protractor';
6 | import { storySettings } from '../../../stories/CloseButton/storySettings';
7 | import {Skin, Size} from './constants';
8 |
9 | describe('CloseButton', () => {
10 | const storyUrl = createStoryUrl(storySettings);
11 | const dataHook = 'storybook-close-button';
12 |
13 | beforeAll(() => browser.get(storyUrl));
14 |
15 | eyes.it('should render all skins', async () => {
16 | const driver = closeButtonTestkitFactory({ dataHook });
17 | await waitForVisibilityOf(driver.element());
18 | for (let skin in enumValues(Skin)) {
19 | await eyes.checkWindow(`skin=${skin}`);
20 | }
21 | });
22 |
23 | });
24 |
--------------------------------------------------------------------------------
/src/components/CloseButton/CloseButton.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {buttonDriverFactory as closeButtonDriverFactory, ButtonDriver as CloseButtonDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/CloseButton/CloseButton.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { createDriverFactory } from 'wix-ui-test-utils/driver-factory';
3 | import { closeButtonDriverFactory } from './CloseButton.driver';
4 | import { closeButtonTestkitFactory } from '../../testkit';
5 | import { closeButtonTestkitFactory as enzymeCloseButtonTestkitFactory } from '../../testkit/enzyme';
6 | import { runTestkitExistsSuite } from '../../common/testkitTests';
7 | import { CloseButton, CloseButtonProps } from './CloseButton';
8 | import { Skin, Size } from './constants';
9 | import { enumValues } from '../../utils';
10 | const defaults = require('lodash/defaults');
11 |
12 | describe('CloseButton', () => {
13 | const createDriver = createDriverFactory(closeButtonDriverFactory);
14 | const CloseButtonWithDefaults = withDefaultsHOC(CloseButton,
15 | {
16 | children: 'Click me!'
17 | });
18 |
19 | describe('skin prop', () => {
20 | it('should be standard by default', () => {
21 | const driver = createDriver();
22 | expect(driver.getSkin()).toBe(Skin.standard);
23 | });
24 |
25 | enumValues(Skin).forEach((skin: Skin) => {
26 | it(`should be '${skin}'`, () => {
27 | const driver = createDriver();
28 | expect(driver.getSkin()).toBe(skin);
29 | });
30 | });
31 | });
32 |
33 | describe('size prop', () => {
34 | it('should be small by default', () => {
35 | const driver = createDriver();
36 | expect(driver.getSize()).toBe(Size.small);
37 | });
38 |
39 | enumValues(Size).forEach((size: Size) => {
40 | it(`should be '${size}'`, () => {
41 | const driver = createDriver();
42 | expect(driver.getSize()).toBe(size);
43 | });
44 | });
45 | });
46 |
47 | runTestkitExistsSuite({
48 | Element: ,
49 | testkitFactory: closeButtonTestkitFactory,
50 | enzymeTestkitFactory: enzymeCloseButtonTestkitFactory
51 | });
52 | });
53 |
54 |
55 | // TODO: consider putting this in 'test/utils'
56 | /**
57 | * Create a Component with applied default props.
58 | * The new component can receive Partial instead of P.
59 | */
60 | function withDefaultsHOC
(Component: React.SFC
, defaultProps: P): React.SFC> {
61 | return (partialProps?: Partial) => {
62 | return React.createElement(Component, defaults({}, partialProps, defaultProps));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/CloseButton/CloseButton.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: Button;
4 | }
5 |
6 | :import {
7 | -st-from: "../../colors.st.css";
8 | -st-named:
9 | B10, B20, B50,
10 | D10, D20,
11 | WHITE;
12 | }
13 |
14 | .root {
15 | -st-extends: Button;
16 | -st-states: skin(enum(standard, white, dark)), size(enum(small, large));
17 |
18 | box-sizing: border-box;
19 |
20 | display: flex;
21 | justify-content: center;
22 | align-items: center;
23 |
24 | background-color: transparent;
25 | border: none;
26 |
27 | cursor: pointer;
28 | }
29 |
30 | .root:skin(standard) {
31 | color: value(B10);
32 | }
33 |
34 | .root:skin(standard):hover {
35 | color: value(B20);
36 | }
37 |
38 | .root:skin(white) {
39 | color: value(WHITE);
40 | }
41 | .root:skin(white):hover {
42 | color: value(B50);
43 | }
44 |
45 | .root:skin(dark) {
46 | color: value(D10);
47 | }
48 | .root:skin(dark):hover {
49 | color: value(D20);
50 | }
51 |
52 | .root:size(small) {
53 | width: 18px;
54 | height: 18px;
55 | }
56 |
57 | /* svg sizing will be obsolete once we have 2 sets of icons which are based on 18x18 view and 24x24 view */
58 | .root:size(small) svg {
59 | width: 6px;
60 | height: 6px;
61 | }
62 |
63 | .root:size(large) {
64 | width: 24px;
65 | height: 24px;
66 | }
67 | .root:size(large) svg {
68 | width: 8px;
69 | height: 8px;
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/src/components/CloseButton/CloseButton.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | Button as CoreButton,
4 | ButtonProps as CoreButtonProps
5 | } from 'wix-ui-core/dist/src/components/deprecated/button';
6 | import { enumValues } from '../../utils';
7 | import style from './CloseButton.st.css';
8 | import { Skin, Size } from './constants';
9 | import { Close as CloseIcon } from 'wix-ui-icons-common/system';
10 |
11 | export interface CloseButtonOwnProps extends CoreButtonProps {
12 | /**Skin of the Button (Styling)*/
13 | skin?: Skin;
14 | /** Size of the button (Styling) */
15 | size?: Size;
16 | }
17 |
18 | export type CloseButtonProps = CloseButtonOwnProps & CoreButtonProps;
19 |
20 | export const CloseButton: React.SFC = props => {
21 | // children is ommited on purpose (and not used)
22 | const { children, skin, size, ...rest } = props;
23 |
24 | return (
25 |
26 |
27 |
28 | );
29 | };
30 |
31 | CloseButton.displayName = 'CloseButton';
32 |
33 | CloseButton.defaultProps = {
34 | skin: Skin.standard,
35 | size: Size.small
36 | };
37 |
--------------------------------------------------------------------------------
/src/components/CloseButton/constants.ts:
--------------------------------------------------------------------------------
1 | export enum Skin {
2 | standard = 'standard',
3 | white = 'white',
4 | dark = 'dark'
5 | };
6 |
7 | export enum Size {
8 | small = 'small',
9 | large = 'large'
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/CloseButton/index.ts:
--------------------------------------------------------------------------------
1 | export { CloseButton, CloseButtonProps } from './CloseButton';
2 | export { Skin as CloseButtonSkin, Size as CloseButtonSize } from './constants';
--------------------------------------------------------------------------------
/src/components/FloatingHelper/ClosablePopover/ClosablePopover.driver.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BaseDriver,
3 | DriverFactory,
4 | ComponentFactory
5 | } from 'wix-ui-test-utils/driver-factory';
6 | import { popoverDriverFactory } from 'wix-ui-core/drivers/vanilla';
7 |
8 | // TODO: Move this interface to Core's PopoverDriver (big PR with dependencies)
9 | export interface PopoverDriver extends BaseDriver {
10 | exists: () => boolean;
11 | getTargetElement: () => Element;
12 | getContentElement: () => any;
13 | isTargetElementExists: () => boolean;
14 | isContentElementExists: () => boolean;
15 | mouseEnter: () => any;
16 | mouseLeave: () => any;
17 | click: () => any;
18 | clickOutside: () => void;
19 | getArrowOffset: () => {
20 | top: string;
21 | left: string;
22 | right: string;
23 | bottom: string;
24 | };
25 | inlineStyles: () => CSSStyleDeclaration;
26 | getElementId: () => string;
27 | getArrowElement: () => any;
28 | }
29 |
30 | export interface ClosablePopoverDriver extends PopoverDriver {
31 | /** Checks is the popover's content is open */
32 | isOpened: () => boolean;
33 | }
34 |
35 | export const closablePopoverDriverFactory: DriverFactory<
36 | ClosablePopoverDriver & PopoverDriver
37 | > = ({ element, eventTrigger }: ComponentFactory): ClosablePopoverDriver => {
38 | const popoverDriver = popoverDriverFactory({ element, eventTrigger });
39 |
40 | return {
41 | ...popoverDriver,
42 | isOpened: () => popoverDriver.isContentElementExists()
43 | };
44 | };
45 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/ClosablePopover/ClosablePopover.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | import { ElementFinder } from 'protractor';
2 | import { popoverDriverFactory, PopoverDriver } from 'wix-ui-core/drivers/protractor';
3 | import { DriverFactory, BaseDriver } from 'wix-ui-core/dist/src/common/BaseDriver.protractor';
4 |
5 | export interface ClosablePopoverDriver extends PopoverDriver {
6 | isOpened: () => Promise;
7 | }
8 |
9 | export const closablePopoverDriverFactory: DriverFactory = element => {
10 | const popoverDriver = popoverDriverFactory(element);
11 |
12 | return {
13 | ...popoverDriver,
14 | isOpened: async () => popoverDriver.isContentElementExists(),
15 | };
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/ClosablePopover/index.ts:
--------------------------------------------------------------------------------
1 | export * from './ClosablePopover';
--------------------------------------------------------------------------------
/src/components/FloatingHelper/DataHooks.ts:
--------------------------------------------------------------------------------
1 | export const DataHooks = {
2 | innerContent: 'inner-content',
3 | closeButton: 'close-button',
4 | contentWrapper: 'content-wrapper'
5 | };
6 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelper.driver.ts:
--------------------------------------------------------------------------------
1 | import {BaseDriver, DriverFactory} from 'wix-ui-test-utils/driver-factory';
2 | import {closablePopoverDriverFactory,ClosablePopoverDriver} from './ClosablePopover/ClosablePopover.driver';
3 | import {DataHooks} from './DataHooks';
4 | import {floatingHelperContentDriverFactory, FloatingHelperContentDriver} from '../../components/FloatingHelper/FloatingHelperContent/FloatingHelperContent.driver';
5 |
6 | // TODO: add interface of PopoverDriver
7 | export interface FloatingHelperDriver extends ClosablePopoverDriver {
8 | /** Get the driver for the helper's content */
9 | getHelperContentDriver: () => FloatingHelperContentDriver;
10 | /** check wether the helper has a close button */
11 | hasCloseButton: () => boolean;
12 | /** click the close button */
13 | clickCloseButton: () => void;
14 | /** Get width of content's root element */
15 | getWidth: () => string;
16 | }
17 |
18 | export const floatingHelperDriverFactory:
19 | DriverFactory =
20 | ({wrapper, element, eventTrigger}) => {
21 | const closablePopoverDriver = closablePopoverDriverFactory({wrapper, element, eventTrigger});
22 | const popoverContent = () => closablePopoverDriver.getContentElement();
23 | const innerContent = () => popoverContent().querySelector(`[data-hook='${DataHooks.innerContent}']`);
24 | const closeButton = () => popoverContent().querySelector(`[data-hook='${DataHooks.closeButton}']`);
25 | const contentWrapper = () => popoverContent().querySelector(`[data-hook='${DataHooks.contentWrapper}']`);
26 |
27 |
28 | return {
29 | ...closablePopoverDriver,
30 | hasCloseButton: () => !!closeButton(),
31 | clickCloseButton: () => eventTrigger.click(closeButton()),
32 | getHelperContentDriver: () => floatingHelperContentDriverFactory({wrapper, element: innerContent(), eventTrigger}),
33 | getWidth: () => window.getComputedStyle(contentWrapper()).width
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelper.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import { browser, ElementFinder , $} from 'protractor';
3 | import { createStoryUrl, waitForVisibilityOf, scrollToElement } from 'wix-ui-test-utils/protractor';
4 | import * as autoExampleDriver from 'wix-storybook-utils/AutoExampleDriver';
5 | import { floatingHelperTestkitFactory, FloatingHelperDriver } from '../../testkit/protractor';
6 | import { storySettings } from '../../../stories/FloatingHelper/StorySettings';
7 |
8 | describe('FloatingHelper', () => {
9 | let driver: FloatingHelperDriver;
10 |
11 | eyes.it('should be opened by default', async () => {
12 | const storyUrl = createStoryUrl({kind:storySettings.kind, story:storySettings.story, withExamples:false});
13 | await browser.get(storyUrl);
14 | driver = floatingHelperTestkitFactory({ dataHook: storySettings.dataHook });
15 | await waitForVisibilityOf(driver.element(), 'Cannot find FloatingHelper');
16 | expect(await driver.isOpened()).toBeTruthy();
17 | });
18 |
19 | eyes.it('should have appearance light', async () => {
20 | const storyUrl = createStoryUrl({kind:storySettings.kind, story:storySettings.story, withExamples:true});
21 | await browser.get(storyUrl);
22 | driver = floatingHelperTestkitFactory({ dataHook: 'story-floating-helper-light' });
23 | await waitForVisibilityOf(driver.element(), 'Cannot find FloatingHelper');
24 | await scrollToElement($('[data-hook=appearance-light-example-container]'));
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelper.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | import { $, ElementFinder, by } from 'protractor';
2 | import { DriverFactory } from 'wix-ui-core/dist/src/common/BaseDriver.protractor';
3 | import { ClosablePopover } from './ClosablePopover/ClosablePopover';
4 | import { closablePopoverDriverFactory, ClosablePopoverDriver } from './ClosablePopover/ClosablePopover.protractor.driver';
5 | import { DataHooks } from './DataHooks';
6 | import { floatingHelperContentDriverFactory, FloatingHelperContentDriver } from '../../components/FloatingHelper/FloatingHelperContent/FloatingHelperContent.protractor.driver';
7 |
8 | export interface FloatingHelperDriver extends ClosablePopoverDriver {
9 | /** Get HelperContent driver */
10 | getHelperContentDriver: () => FloatingHelperContentDriver;
11 | }
12 |
13 | export const floatingHelperDriverFactory: DriverFactory = (element: ElementFinder): FloatingHelperDriver => {
14 | return {
15 | ...closablePopoverDriverFactory(element),
16 | getHelperContentDriver: () => floatingHelperContentDriverFactory(element.$(byDataHook(DataHooks.innerContent))),
17 | };
18 | };
19 |
20 | export function byDataHook(hook: string) {
21 | return `[data-hook='${hook}']`;
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelper.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: Popover;
4 | }
5 |
6 | :import {
7 | -st-from: "./FloatingHelperContent/FloatingHelperContent.st.css";
8 | -st-default: FloatingHelperContent;
9 | }
10 |
11 | :import {
12 | -st-from: "../Text/Text.st.css";
13 | -st-default: Text;
14 | }
15 |
16 | :import {
17 | -st-from: "../Button/Button.st.css";
18 | -st-default: Button;
19 | }
20 |
21 | :import {
22 | -st-from: "../../colors.st.css";
23 | -st-named: D80, WHITE;
24 | }
25 |
26 | :import {
27 | -st-from: "../../shadows.st.css";
28 | -st-named: shadow30;
29 | }
30 |
31 | :vars {
32 | /* TODO: create and use a fade function */
33 |
34 | /** background color D10 with opacity 0.95 */
35 | backgroundColorDark: rgba(22,45,61,0.95);
36 | backgroundColorLight: value(D80);
37 | closeButtonPadding: 6px;
38 | }
39 |
40 | .root {
41 | -st-states: bounce, placement-right, placement-left, placement-top, placement-bottom, appearance(enum(dark,light));
42 | -st-extends: Popover;
43 | }
44 |
45 | .root:appearance(dark) {
46 | -st-mixin: Popover(
47 | contentBorderColor value(backgroundColorDark),
48 | contentBackgroundColor value(backgroundColorDark),
49 | contentBorderWidth 0,
50 | contentBorderRadius 8px,
51 | contentPadding 0 0
52 | );
53 | }
54 |
55 | .root:appearance(light) {
56 | -st-mixin: Popover(
57 | contentBorderColor value(backgroundColorLight),
58 | contentBackgroundColor value(backgroundColorLight),
59 | contentBorderWidth 0,
60 | contentBorderRadius 8px,
61 | contentPadding 0 0
62 | );
63 | }
64 |
65 | .root::arrow {
66 | z-index: 2;
67 | }
68 |
69 | /* popoverContent and innerContent are taken from Tooltip.tooltipContent,
70 | * but I split them.
71 | */
72 | .root::popoverContent {
73 | position: relative;
74 | box-sizing: border-box;
75 | box-shadow: value(shadow30);
76 | }
77 |
78 | .closeButton {
79 | position: absolute;
80 | top: value(closeButtonPadding);
81 |
82 | /* default dir=ltr */
83 | right: value(closeButtonPadding);
84 | left: initial;
85 | }
86 |
87 | :global([dir="rtl"]) .closeButton {
88 | right: initial;
89 | left: value(closeButtonPadding);
90 | }
91 |
92 | .innerContent {
93 | padding: 30px 36px;
94 | color: value(WHITE);
95 | }
96 |
97 |
98 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/DataHooks.ts:
--------------------------------------------------------------------------------
1 | export const DataHooks = {
2 | title: 'helper-content-title',
3 | body: 'helper-content-body',
4 | actionButton: 'helper-content-action-button',
5 | image: 'helper-content-image',
6 | footer: 'helper-content-footer'
7 | };
8 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/FloatingHelperContent.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import { browser, ElementFinder } from 'protractor';
3 | import { getStoryUrl, waitForVisibilityOf, scrollToElement, protractorTestkitFactoryCreator } from 'wix-ui-test-utils/protractor';
4 | import { floatingHelperContentDriverFactory, FloatingHelperContentDriver } from './FloatingHelperContent.protractor.driver';
5 | import { storySettings } from '../../../../stories/FloatingHelperContent/StorySettings';
6 |
7 |
8 | export const floatingHelperContentTestkitFactory = protractorTestkitFactoryCreator(floatingHelperContentDriverFactory);
9 |
10 | describe('FloatingHelperContent', () => {
11 | const storyUrl = getStoryUrl(storySettings.kind, storySettings.story);
12 |
13 | beforeEach(async () => {
14 | await browser.get(storyUrl);
15 | });
16 |
17 | describe('FloatingHelperContent variations', () => {
18 | storySettings.exampleDataHooks.forEach(dataHook => {
19 | eyes.it(`should display example with dataHook ${dataHook}`, async () => {
20 | const driver = floatingHelperContentTestkitFactory({ dataHook });
21 | await scrollToElement(driver.element());
22 | await waitForVisibilityOf(driver.element(), 'Cannot find FloatingHelperContent');
23 | });
24 | });
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/FloatingHelperContent.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | import {ElementFinder} from 'protractor';
2 | import {DataHooks} from './DataHooks';
3 | import {DriverFactory, BaseDriver} from 'wix-ui-core/dist/src/common/BaseDriver.protractor';
4 | import {textDriverFactory} from '../../../components/Text/Text.protractor.driver';
5 |
6 | export interface FloatingHelperContentDriver extends BaseDriver {
7 | hasActionButton: () => Promise;
8 | }
9 |
10 | export const floatingHelperContentDriverFactory: DriverFactory = element => {
11 | const actionButton = () => element.$(byDataHook(DataHooks.actionButton));
12 |
13 | return {
14 | element: () => element,
15 | hasActionButton: async () => actionButton().isPresent(),
16 | };
17 | };
18 |
19 | export function byDataHook(hook: string) {
20 | return `[data-hook='${hook}']`;
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/FloatingHelperContent.st.css:
--------------------------------------------------------------------------------
1 | .root {
2 | -st-states: hasBody(boolean), appearance(enum(dark,light));
3 |
4 | display: flex;
5 | flex-direction: row;
6 | }
7 |
8 | .root:hasBody .title {
9 | margin-bottom: 6px;
10 | }
11 |
12 | .action {
13 | margin-top: 18px;
14 | }
15 |
16 | .image {
17 | margin-left: 18px;
18 | display: flex;
19 | }
20 |
21 | .footer {
22 | margin-top: 12px;
23 | display: flex;
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/README.md:
--------------------------------------------------------------------------------
1 | # ``
2 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/constants.ts:
--------------------------------------------------------------------------------
1 | export enum ActionButtonTheme {
2 | standard = 'standard',
3 | white = 'white',
4 | premium = 'premium',
5 | lightPrimary = 'lightPrimary'
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/FloatingHelperContent/index.ts:
--------------------------------------------------------------------------------
1 | export * from './FloatingHelperContent';
2 | export * from './constants';
3 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/README.md:
--------------------------------------------------------------------------------
1 | # ``
2 |
3 | This is a Popover helper component
4 |
5 | ### Open/Close behavior
6 | This component can be Controlled or Uncontrolled according to wether the `opened` property is defined or undefined.
7 | In Uncontrolled mode, the default behavior is that the popover content is opened when mouse-enter is triggered on the target, an closes when the close button is clicked.
8 |
9 | ### Programatic Open/Close
10 | Works only in Uncontrolled mode.
11 | See "Programatic Open Example".
12 |
13 | ### Playground & Preview
14 | The playground's live Code section is not working well for this component. Please refer to the Examples section, and click "Show code" to see code examples.
15 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/constants.ts:
--------------------------------------------------------------------------------
1 | export enum Appearance {
2 | dark = 'dark',
3 | light = 'light'
4 | }
5 |
--------------------------------------------------------------------------------
/src/components/FloatingHelper/index.ts:
--------------------------------------------------------------------------------
1 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
2 | import {FloatingHelper as FLoatingHelperRaw} from './FloatingHelper';
3 | export * from './FloatingHelper';
4 | export const FloatingHelper = createHOC(FLoatingHelperRaw);
5 |
6 | export * from './constants';
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.driver.ts:
--------------------------------------------------------------------------------
1 | import {BaseDriver, DriverFactory} from 'wix-ui-test-utils/driver-factory';
2 |
3 | export interface FullTextViewDriver extends BaseDriver {
4 | getText: () => string;
5 | getTagName: () => string;
6 | }
7 |
8 | export const fullTextViewDriverFactory: DriverFactory = ({element}) => {
9 | return {
10 | /** check if element exists */
11 | exists: () => !!element,
12 | /** get the rendered content */
13 | getText: () => element.innerHTML,
14 | /** get the rendered tag name */
15 | getTagName: () => element.tagName.toLowerCase(),
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import { browser } from 'protractor';
3 | import { waitForVisibilityOf, createStoryUrl } from 'wix-ui-test-utils/protractor';
4 | import { fullTextViewTestkitFactory } from '../../testkit/protractor';
5 |
6 | describe('FullTextView', () => {
7 | const dataHook = 'storybook-fullTextView';
8 | const storyUrl = createStoryUrl({
9 | kind: 'Components',
10 | story: 'FullTextView'
11 | });
12 |
13 | beforeEach(() => browser.get(storyUrl));
14 |
15 | eyes.it('should render with default props', async () => {
16 | const driver = fullTextViewTestkitFactory({ dataHook });
17 | await waitForVisibilityOf(driver.element());
18 | expect(await driver.element().isPresent()).toBeTruthy();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | import {ElementFinder} from 'protractor';
2 | import { DriverFactory } from 'wix-ui-core/dist/src/common/BaseDriver.protractor';
3 |
4 | export interface FullTextViewDriver {
5 | element: () => ElementFinder;
6 | getText: () => Promise;
7 | }
8 |
9 | export const fullTextViewDriverFactory: DriverFactory = component => ({
10 | /** returns the component element */
11 | element: () => component,
12 | /** returns the component text */
13 | getText: async () => component.getText()
14 | });
15 |
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {createDriverFactory} from 'wix-ui-test-utils/driver-factory';
3 | import {isEnzymeTestkitExists} from 'wix-ui-test-utils/enzyme';
4 | import {isTestkitExists} from 'wix-ui-test-utils/vanilla';
5 | import {mount} from 'enzyme';
6 | import {fullTextViewDriverFactory} from './FullTextView.driver';
7 | import {fullTextViewUniDriverFactory} from './FullTextView.uni.driver';
8 | import {FullTextView} from './FullTextView';
9 |
10 | import {fullTextViewTestkitFactory} from '../../testkit';
11 | import {fullTextViewTestkitFactory as enzymeFullTextViewTestkitFactory} from '../../testkit/enzyme';
12 | import {createUniDriverFactory} from 'wix-ui-test-utils/dist/src/uni-driver-factory';
13 |
14 | describe('FullTextView', () => {
15 | describe('[sync]', () => {
16 | runTests(createDriverFactory(fullTextViewDriverFactory));
17 | });
18 |
19 | describe('[async]', () => {
20 | runTests(createUniDriverFactory(fullTextViewUniDriverFactory));
21 | });
22 |
23 | function runTests(createDriver) {
24 | it('should render a span tag by default', async () => {
25 | const wrapper = createDriver(Hello World);
26 | expect(await wrapper.getTagName()).toBe('span');
27 | });
28 |
29 | it('should display full content on hover and hide it on leave in tooltip', async () => {
30 | const content = (
31 |
32 | Delete this super awesome thing
33 | ?
34 |
35 | );
36 | const component = mount({content});
37 |
38 | expect(component.find('[data-hook="popover-content"]').length).toBe(0);
39 | component.setState({isEllipsisActive: true});
40 | component.simulate('mouseEnter');
41 | expect(component.find('[data-hook="popover-content"]').at(0).text()).toBe('Delete this super awesome thing?');
42 | });
43 |
44 | describe('testkit', () => {
45 | it('should exist', () => {
46 | expect(isTestkitExists(Hello World,
47 | fullTextViewTestkitFactory)).toBe(true);
48 | });
49 | });
50 |
51 | describe('enzyme testkit', () => {
52 | it('should exist', () => {
53 | expect(isEnzymeTestkitExists(Hello World,
54 | enzymeFullTextViewTestkitFactory, mount)).toBe(true);
55 | });
56 | });
57 | }
58 | });
59 |
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.st.css:
--------------------------------------------------------------------------------
1 | .root {
2 | display: inline-block;
3 | text-overflow: ellipsis;
4 | overflow: hidden;
5 | white-space: nowrap;
6 | width: 100%;
7 | }
8 |
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as shallowequal from 'shallowequal';
3 | import {Tooltip} from '../Tooltip';
4 | import style from './FullTextView.st.css';
5 |
6 | export interface FullTextViewProps {
7 | children?: React.ReactNode;
8 | maxWidth?: number | string;
9 | }
10 |
11 | export interface FullTextViewState {
12 | isEllipsisActive: boolean;
13 | }
14 |
15 | const isEllipsisActive = (node: HTMLElement) => node && node.offsetWidth < node.scrollWidth;
16 |
17 | export class FullTextView extends React.Component {
18 | static displayName = 'FullTextView';
19 |
20 | private textNode: any;
21 | private ellipsesTimeout: any;
22 |
23 | state = {
24 | isEllipsisActive: false
25 | }
26 |
27 | componentDidMount() {
28 | window.addEventListener('resize', this.updateEllipsesState);
29 | this.updateEllipsesState();
30 | }
31 |
32 | componentDidUpdate(prevProps) {
33 | // if props changed, then we want to re-check node for ellipsis state
34 | // and we can not do such check in render, because we want to check already rendered node
35 | if (!shallowequal(prevProps, this.props)) {
36 | this.updateEllipsesState();
37 | }
38 | }
39 |
40 | componentWillUnmount() {
41 | window.removeEventListener('resize', this.updateEllipsesState);
42 | }
43 |
44 | handleTextRef = node => this.textNode = node;
45 |
46 | updateEllipsesState = () => {
47 | clearTimeout(this.ellipsesTimeout);
48 | this.ellipsesTimeout = setTimeout(() => {
49 | this.setState({isEllipsisActive: isEllipsisActive(this.textNode)})
50 | }, 30);
51 | };
52 |
53 | renderText() {
54 | return (
55 |
60 | {this.props.children}
61 |
62 | );
63 | }
64 |
65 | render() {
66 | if (!this.state.isEllipsisActive) {
67 | return this.renderText();
68 | }
69 |
70 | return (
71 |
72 | {this.renderText()}
73 |
74 | );
75 | }
76 | };
77 |
--------------------------------------------------------------------------------
/src/components/FullTextView/FullTextView.uni.driver.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | BaseUniDriver,
3 | baseUniDriverFactory,
4 | } from 'wix-ui-test-utils/base-driver';
5 | import {UniDriver} from 'wix-ui-test-utils/unidriver';
6 |
7 | export interface FullTextViewUniDriver extends BaseUniDriver {
8 | getText: () => Promise;
9 | getTagName: () => Promise;
10 | }
11 |
12 | export const fullTextViewUniDriverFactory = (base: UniDriver): FullTextViewUniDriver => {
13 | return {
14 | ...baseUniDriverFactory(base),
15 | getText: () => base.text() as Promise,
16 | getTagName: async () => (await base._prop('tagName')).toLowerCase() as Promise,
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/components/FullTextView/index.ts:
--------------------------------------------------------------------------------
1 | import {FullTextView as FullTextViewComponent} from './FullTextView';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const FullTextView = createHOC(FullTextViewComponent);
5 |
--------------------------------------------------------------------------------
/src/components/HBox/HBox.driver.ts:
--------------------------------------------------------------------------------
1 | export const hBoxDriverFactory = ({element}) => {
2 | return {
3 | /** check if element exists */
4 | exists: () => !!element,
5 | /** get the rendered content */
6 | getChildren: () => element.innerHTML
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/HBox/HBox.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {hBoxTestkitFactory} from '../../testkit/protractor';
5 |
6 | describe('HBox', () => {
7 | const storyUrl = getStoryUrl('Components', 'HBox');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should display correct content', () => {
11 | const dataHook = 'storybook-hbox';
12 | const driver = hBoxTestkitFactory({dataHook});
13 |
14 | return waitForVisibilityOf(driver.element(), 'Cannot find HBox');
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/components/HBox/HBox.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export const hBoxDriverFactory = component => ({
2 | /** Returns the wrapped component instance */
3 | element: () => component
4 | });
5 |
--------------------------------------------------------------------------------
/src/components/HBox/HBox.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {mount} from 'enzyme';
3 | import {HBox} from './';
4 |
5 | describe('HBox', () => {
6 | let wrapper;
7 |
8 | afterEach(() => wrapper.detach());
9 |
10 | it('should render the passed children', () => {
11 | wrapper = mount(1
, {attachTo: document.createElement('div')});
12 | expect(wrapper.html()).toContain('1
');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/components/HBox/HBox.st.css:
--------------------------------------------------------------------------------
1 | .root {
2 | -st-states: verticalAlignment(enum(bottom, center, top));
3 | display: flex;
4 | flex-wrap: wrap;
5 | width: 100%;
6 | height: 100%;
7 | }
8 |
9 | .root:verticalAlignment(bottom) {
10 | align-items: flex-end;
11 | }
12 |
13 | .root:verticalAlignment(center) {
14 | align-items: center;
15 | }
16 |
17 | .root:verticalAlignment(top) {
18 | align-items: flex-start;
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/components/HBox/HBox.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import style from './HBox.st.css';
3 | import {addSpacing} from './utils';
4 |
5 | export interface HBoxProps {
6 | children?: React.ReactNode;
7 | verticalAlignment?: Alignment;
8 | spacing?: number;
9 | dir?: 'ltr' | 'rtl';
10 | }
11 |
12 | export type Alignment = 'top' | 'center' | 'bottom';
13 |
14 | const defaultProps: HBoxProps = {
15 | children: null,
16 | verticalAlignment: 'top',
17 | spacing: 0,
18 | dir: 'ltr'
19 | };
20 |
21 | /**
22 | * HBox
23 | */
24 | export const HBox: React.SFC = props => {
25 | const {children, verticalAlignment, spacing, dir} = props;
26 | return {addSpacing(children, spacing, dir)}
;
27 | };
28 |
29 | HBox.displayName = 'HBox';
30 |
31 | HBox.defaultProps = defaultProps;
32 |
--------------------------------------------------------------------------------
/src/components/HBox/index.ts:
--------------------------------------------------------------------------------
1 | export {HBox, HBoxProps} from './HBox';
2 |
--------------------------------------------------------------------------------
/src/components/HBox/utils.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export function addSpacing(children, spacing: number, dir?: 'ltr' | 'rtl') {
4 | if (!children || !spacing) {
5 | return children;
6 | }
7 |
8 | const spacedChildren = [];
9 | const marginProperty = dir === 'rtl' ? 'marginLeft' : 'marginRight';
10 |
11 | for (let i = 0; i < children.length - 1; i++) {
12 | spacedChildren.push(
13 | React.cloneElement(children[i], {style: {[marginProperty]: spacing}})
14 | );
15 | }
16 |
17 | spacedChildren.push(children[children.length - 1]);
18 |
19 | return spacedChildren;
20 | }
21 |
--------------------------------------------------------------------------------
/src/components/Heading/Heading.driver.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFactory } from 'wix-ui-test-utils/driver-factory';
2 | import { textDriverFactory, TextDriver } from '../core/CoreText/Text.driver';
3 | import { StylableDOMUtil } from '@stylable/dom-test-kit';
4 | import style from './Heading.st.css';
5 | import { Appearance } from './Heading';
6 |
7 | export interface HeadingDriver extends TextDriver {
8 | getAppearance: () => Appearance;
9 | isLight: () => boolean;
10 | }
11 |
12 | export const headingDriverFactory = (factoryParams: ComponentFactory): HeadingDriver => {
13 | const coreTextDriver = textDriverFactory(factoryParams);
14 | const stylableDOMUtil = new StylableDOMUtil(style);
15 | const { element } = factoryParams;
16 |
17 | return {
18 | ...coreTextDriver,
19 | getAppearance: () => stylableDOMUtil.getStyleState(element, 'appearance') as Appearance,
20 | isLight: () => stylableDOMUtil.hasStyleState(element, 'light'),
21 | };
22 | };
23 |
--------------------------------------------------------------------------------
/src/components/Heading/Heading.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {headingTestkitFactory} from '../../testkit/protractor';
5 |
6 | describe('Heading', () => {
7 | const storyUrl = getStoryUrl('Components', 'Heading');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should display correct content', () => {
11 | const dataHook = 'storybook-heading';
12 | const driver = headingTestkitFactory({dataHook});
13 |
14 | return waitForVisibilityOf(driver.element(), 'Cannot find Heading')
15 | .then(() => expect(driver.getText()).toBe('Some text'));
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/components/Heading/Heading.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {textDriverFactory as headingDriverFactory, TextDriver as HeadingDriver} from '../core/CoreText/Text.protractor.driver';
2 |
--------------------------------------------------------------------------------
/src/components/Heading/Heading.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {headingDriverFactory} from './Heading.driver';
3 | import {Heading} from './';
4 | import {Appearance} from './Heading';
5 | import {createDriverFactory} from 'wix-ui-test-utils/driver-factory';
6 | import {isEnzymeTestkitExists} from 'wix-ui-test-utils/enzyme';
7 | import {isTestkitExists} from 'wix-ui-test-utils/vanilla';
8 | import {mount} from 'enzyme';
9 | import {headingTestkitFactory} from '../../testkit';
10 | import {headingTestkitFactory as enzymeHeadingTestkitFactory} from '../../testkit/enzyme';
11 |
12 | describe('Heading', () => {
13 | const createDriver = createDriverFactory(headingDriverFactory);
14 |
15 | describe('appearance prop', () => {
16 | it('should render a h1 tag by default', () => {
17 | const wrapper = createDriver(Hello);
18 | expect(wrapper.getTagName()).toBe('h1');
19 | expect(wrapper.getAppearance()).toBe('H1');
20 | });
21 |
22 | ['H2', 'H3', 'H4'].forEach((appearance: Appearance) => {
23 | it(`should render a ${appearance.toLowerCase()} tag`, () => {
24 | const wrapper = createDriver(Hello);
25 | expect(wrapper.getTagName()).toBe(appearance.toLocaleLowerCase());
26 | expect(wrapper.getAppearance()).toBe(appearance);
27 | });
28 | });
29 | });
30 |
31 | describe('light prop', () => {
32 | it('should be dark by default', () => {
33 | const wrapper = createDriver(Hello);
34 | expect(wrapper.isLight()).toBe(false);
35 | });
36 |
37 | it('should be light', () => {
38 | const wrapper = createDriver(Hello);
39 | expect(wrapper.isLight()).toBe(true);
40 | });
41 | });
42 |
43 | describe('testkit', () => {
44 | it('should exist', () => {
45 | expect(isTestkitExists(Hello World, headingTestkitFactory)).toBe(true);
46 | });
47 | });
48 |
49 | describe('enzyme testkit', () => {
50 | it('should exist', () => {
51 | expect(isEnzymeTestkitExists(Hello World, enzymeHeadingTestkitFactory, mount)).toBe(true);
52 | });
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/src/components/Heading/Heading.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {Text as CoreText, TextProps as CoreTextProps} from '../core/CoreText';
3 | import style from './Heading.st.css';
4 | import {withStylable} from 'wix-ui-core/dist/src/utils/withStylable';
5 |
6 | export enum Appearance {
7 | H1 = 'H1',
8 | H2 = 'H2',
9 | H3 = 'H3',
10 | H4 = 'H4'
11 | };
12 | export type TagName = 'h1' | 'h2' | 'h3' | 'h4';
13 |
14 | export interface Props {
15 | /** any nodes to be rendered (usually text nodes) */
16 | children?: React.ReactNode;
17 |
18 | /** is the text has dark or light skin */
19 | light?: boolean;
20 |
21 | /** typography of the heading */
22 | appearance?: Appearance;
23 | }
24 |
25 | export interface State { tagName: TagName; }
26 |
27 | const defaultProps: Props = {
28 | appearance: Appearance.H1,
29 | light: false
30 | };
31 |
32 | const StyledText = withStylable(
33 | CoreText,
34 | style,
35 | ({light, appearance}) => ({light, appearance}),
36 | defaultProps
37 | );
38 |
39 |
40 | export class Heading extends React.PureComponent {
41 | static displayName = 'Heading';
42 |
43 | static defaultProps: Props = defaultProps;
44 |
45 | state = {tagName: (this.props.appearance.toLowerCase()) as TagName}
46 |
47 | render() {
48 | return (
49 |
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/components/Heading/index.ts:
--------------------------------------------------------------------------------
1 | import {Heading as HeadingComponent} from './Heading';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const Heading = createHOC(HeadingComponent);
5 |
--------------------------------------------------------------------------------
/src/components/Input/Error.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "../../colors.st.css";
3 | -st-named:
4 | R10,
5 | WHITE;
6 | }
7 |
8 | .root {
9 | width: 21px;
10 | height: 21px;
11 | border-radius: 50%;
12 | display: flex;
13 | justify-content: center;
14 | align-items: center;
15 | background: value(R10);
16 | }
17 |
18 | .root svg {
19 | fill: value(WHITE);
20 | }
21 |
--------------------------------------------------------------------------------
/src/components/Input/Input.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {getStoryUrl} from 'wix-ui-test-utils/protractor';
3 | import {inputTestkitFactory} from 'wix-ui-core/dist/src/testkit/protractor';
4 | import {browser} from 'protractor';
5 |
6 | describe('Input', () => {
7 | const storyUrl = getStoryUrl('Components', 'Input');
8 | const dataHook = 'storybook-input';
9 |
10 | beforeEach(() => browser.get(storyUrl));
11 |
12 | eyes.it('should render', () => {
13 | const driver = inputTestkitFactory({dataHook});
14 |
15 | expect(driver.element().isDisplayed()).toBe(true);
16 | }, {version: 'story with value'});
17 | });
18 |
--------------------------------------------------------------------------------
/src/components/Input/Input.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: Input;
4 | }
5 |
6 | :import {
7 | -st-from: "../../colors.st.css";
8 | -st-named:
9 | B20, B30, B40, B50,
10 | D10, D50, D55, D60,
11 | GR20,
12 | R10,
13 | WHITE
14 | }
15 |
16 | :import {
17 | -st-from: "../../typography.st.css";
18 | -st-named: fontRoman;
19 | }
20 |
21 | :import {
22 | -st-from: "./InputStates.st.css";
23 | -st-named: input-large, input-medium, input-small;
24 | }
25 |
26 | /* Input colors */
27 | :vars {
28 | inputBackground: value(WHITE);
29 | inputBorderColor: value(B30);
30 | inputHover: value(B50);
31 | inputFocusBorderColor: value(B20);
32 | inputDisabledColor: value(D55);
33 | inputDisabledBorderColor: value(D60);
34 | inputDisabledHoverBorderColor: value(GR20);
35 | }
36 |
37 | .root {
38 | -st-extends: Input;
39 | -st-states: size(enum(large, medium, small));
40 |
41 | display: flex;
42 | align-items: center;
43 | position: relative;
44 | box-sizing: border-box;
45 | color: value(D10);
46 | width: 100%;
47 | border-radius: 6px;
48 | border: 1px solid value(inputBorderColor);
49 | background-color: value(inputBackground);
50 | padding: 0 6px;
51 | }
52 |
53 | .root:error,
54 | .root:error:focus {
55 | border-color: value(R10);
56 | }
57 |
58 | .root:hover {
59 | background-color: value(inputHover);
60 | }
61 |
62 | .root:disabled {
63 | background-color: inherit;
64 | }
65 |
66 | .root:disabled {
67 | color: value(inputDisabledColor);
68 | border-color: value(inputDisabledBorderColor);
69 | }
70 |
71 | .root:disabled::nativeInput {
72 | color: value(inputDisabledColor);
73 | }
74 |
75 | .root:focus {
76 | border-color: value(inputFocusBorderColor);
77 | }
78 |
79 | .root::nativeInput {
80 | background-color: transparent;
81 | outline: none;
82 | width: 100%;
83 | font-family: value(fontRoman);
84 | border: none;
85 | padding: 0 6px;
86 | }
87 |
88 | .root::nativeInput::-webkit-input-placeholder { color: value(D50); }
89 | .root::nativeInput:-moz-placeholder { color: value(D50); }
90 | .root::nativeInput::-moz-placeholder { color: value(D50); }
91 | .root::nativeInput:-ms-input-placeholder { color: value(D50); }
92 |
93 | .root::nativeInput::selection { background: value(B40); }
94 | .root::nativeInput:-moz-selection { background: value(B40); }
95 |
96 | .root:size(large) {
97 | -st-mixin: input-large;
98 | }
99 |
100 | .root:size(medium) {
101 | -st-mixin: input-medium;
102 | }
103 |
104 | .root:size(small) {
105 | -st-mixin: input-small;
106 | }
107 |
--------------------------------------------------------------------------------
/src/components/Input/Input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | Input as CoreInput,
4 | InputProps as CoreInputProps
5 | } from 'wix-ui-core/dist/src/components/input';
6 | import { withStylable } from 'wix-ui-core/dist/src/utils/withStylable';
7 | import style from './Input.st.css';
8 | import { getInputSuffix } from './InputSuffixes';
9 |
10 | export interface InputProps {
11 | // The size of the input
12 | size?: 'large' | 'medium' | 'small';
13 | }
14 |
15 | const defaultProps = {
16 | size: 'medium'
17 | };
18 |
19 | export const StyledInput = withStylable(
20 | CoreInput,
21 | style,
22 | ({ size }) => ({ size }),
23 | defaultProps
24 | );
25 |
26 | export const Input: React.SFC = (
27 | props: CoreInputProps & InputProps
28 | ) => {
29 | const { error, disabled, suffix } = props;
30 |
31 | return (
32 |
36 | );
37 | };
38 |
39 | Input.displayName = 'Input';
40 |
--------------------------------------------------------------------------------
/src/components/Input/InputStates.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "./Input.st.css";
3 | -st-named: Input;
4 | }
5 |
6 | :import {
7 | -st-from: "../../colors.st.css";
8 | -st-named:
9 | R10,
10 | }
11 |
12 | :import {
13 | -st-from: "wix-ui-core/dist/src/mixins/calc";
14 | -st-default: calc;
15 | }
16 |
17 | :vars {
18 | largeFont: 22px;
19 | medFont: 16px;
20 | smallFont: 14px;
21 |
22 | largeHeight: 60px;
23 | medHeight: 36px;
24 | smallHeight: 30px;
25 | }
26 |
27 | .input-error {
28 | color: value(R10);
29 | border-color: value(R10);
30 | }
31 |
32 | .input-large {
33 | -st-extends: Input;
34 | }
35 |
36 | .input-large::nativeInput {
37 | height: value(largeHeight);
38 | line-height: calc(value(largeHeight) - 2px);
39 | font-size: value(largeFont);
40 | }
41 |
42 | .input-medium {
43 | -st-extends: Input;
44 | }
45 |
46 | .input-medium::nativeInput {
47 | height: value(medHeight);
48 | line-height: calc(value(medHeight) - 2px);
49 | font-size: value(medFont);
50 | }
51 |
52 | .input-small {
53 | -st-extends: Input;
54 | }
55 |
56 | .input-small::nativeInput {
57 | height: value(smallHeight);
58 | line-height: calc(value(smallHeight) - 2px);
59 | font-size: value(smallFont);
60 | }
61 |
--------------------------------------------------------------------------------
/src/components/Input/InputSuffixes.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import FormFieldError from 'wix-ui-icons-common/system/FormFieldError';
3 | import {Tooltip} from '../Tooltip';
4 | import style from './Error.st.css';
5 |
6 | const ErrorComponent = () => (
7 |
8 |
9 |
10 | );
11 |
12 | const getInputErrorSuffix = (error: boolean | string) => {
13 | if (error === true) {
14 | return ;
15 | }
16 |
17 | return (
18 |
19 |
20 |
21 | );
22 | };
23 |
24 | export const getInputSuffix = ({error, disabled, suffix}) => {
25 | if (!error || disabled) {
26 | return suffix;
27 | }
28 |
29 | return getInputErrorSuffix(error);
30 | };
31 |
--------------------------------------------------------------------------------
/src/components/Input/index.ts:
--------------------------------------------------------------------------------
1 | export {Input, InputProps} from './Input';
2 | export {getInputSuffix} from './InputSuffixes';
3 |
--------------------------------------------------------------------------------
/src/components/Label/Label.driver.ts:
--------------------------------------------------------------------------------
1 | import {labelDriverFactory as CoreLabelDriverFactory} from 'wix-ui-core/drivers/vanilla';
2 | import {StylableDOMUtil} from '@stylable/dom-test-kit';
3 | import style from './Label.st.css';
4 |
5 | export const labelDriverFactory = ({element, eventTrigger}) => {
6 | const coreLabelDriver = CoreLabelDriverFactory({element, eventTrigger});
7 | const stylableDOMUtil = new StylableDOMUtil(style);
8 |
9 | return {
10 | ...coreLabelDriver,
11 | getSize: () => stylableDOMUtil.getStyleState(element, 'size')
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/Label/Label.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {labelTestkitFactory} from '../../testkit/protractor';
5 |
6 | describe('Label', () => {
7 | const storyUrl = getStoryUrl('Components', 'Label');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should display correct content', () => {
11 | const dataHook = 'storybook-label';
12 | const driver = labelTestkitFactory({dataHook});
13 |
14 | return waitForVisibilityOf(driver.element(), 'Cannot find Label')
15 | .then(() => expect(driver.getLabelText()).toBe('Some label'));
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/components/Label/Label.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {labelDriverFactory, LabelDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/Label/Label.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {labelDriverFactory} from './Label.driver';
3 | import {labelUniDriverFactory} from './Label.uni.driver';
4 | import {Label} from './';
5 | import {Size} from './constants';
6 | import {createDriverFactory} from 'wix-ui-test-utils/driver-factory';
7 | import {createUniDriverFactory} from 'wix-ui-test-utils/uni-driver-factory';
8 | import {isEnzymeTestkitExists} from 'wix-ui-test-utils/enzyme';
9 | import {isTestkitExists} from 'wix-ui-test-utils/vanilla';
10 | import {mount} from 'enzyme';
11 | import {labelTestkitFactory} from '../../testkit';
12 | import {labelTestkitFactory as enzymeLabelTestkitFactory} from '../../testkit/enzyme';
13 |
14 | describe('Label', () => {
15 |
16 | describe('[sync]', () => {
17 | runTests(createDriverFactory(labelDriverFactory));
18 | });
19 |
20 | describe('[async]', () => {
21 | runTests(createUniDriverFactory(labelUniDriverFactory));
22 | });
23 |
24 | function runTests(createDriver) {
25 | describe('size prop', () => {
26 | it('should be medium by default', async() => {
27 | const wrapper = createDriver();
28 | expect(await wrapper.getSize()).toBe('medium');
29 | });
30 |
31 | it('should be small', async () => {
32 | const wrapper = createDriver();
33 | expect(await wrapper.getSize()).toBe('small');
34 | });
35 | });
36 |
37 | describe('children prop', () => {
38 | it('renders', async () => {
39 | const wrapper = createDriver();
40 | expect(await wrapper.getLabelText()).toBe('Hello');
41 | });
42 | });
43 | }
44 |
45 | describe('testkit', () => {
46 | it('should exist', () => {
47 | expect(isTestkitExists(, labelTestkitFactory)).toBe(true);
48 | });
49 | });
50 |
51 | describe('enzyme testkit', () => {
52 | it('should exist', () => {
53 | expect(isEnzymeTestkitExists(, enzymeLabelTestkitFactory, mount)).toBe(true);
54 | });
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/src/components/Label/Label.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: Label;
4 | }
5 |
6 | :import {
7 | -st-from: "../../colors.st.css";
8 | -st-named:
9 | D20,
10 | }
11 |
12 | :import {
13 | -st-from: "../../typography.st.css";
14 | -st-named: fontLight;
15 | }
16 |
17 | .root {
18 | -st-extends: Label;
19 | -st-states: size(enum(small, medium));
20 | color: value(D20);
21 | font-family: value(fontLight);
22 | }
23 |
24 | .root:size(medium) {
25 | font-size: 16px;
26 | line-height: 24px;
27 | }
28 |
29 | .root:size(small) {
30 | font-size: 14px;
31 | line-height: 18px;
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/Label/Label.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | Label as CoreLabel,
4 | LabelProps as CoreLabelProps
5 | } from 'wix-ui-core/dist/src/components/deprecated/label';
6 | import style from './Label.st.css';
7 | import { Size, SIZES } from './constants';
8 |
9 | export interface LabelProps {
10 | /** size of the label */
11 | size?: Size;
12 | }
13 |
14 | export const Label: React.SFC = (props: CoreLabelProps & LabelProps) => {
15 | const {size, className,...rest} = props;
16 | return
17 | };
18 |
19 | Label.defaultProps = {
20 | size: SIZES.medium
21 | };
22 |
23 | Label.displayName = 'Label';
24 |
--------------------------------------------------------------------------------
/src/components/Label/Label.uni.driver.ts:
--------------------------------------------------------------------------------
1 | import {UniDriver} from 'wix-ui-test-utils/unidriver';
2 | import {labelUniDriverFactory as coreLabelUniDriverFactory,LabelDriver as CoreLabelDriver} from 'wix-ui-core/dist/src/components/deprecated/label/Label.uni.driver';
3 |
4 | import {Size} from './constants';
5 |
6 | export interface LabelDriver extends CoreLabelDriver {
7 | /**
8 | * Get size
9 | */
10 | getSize: () => Promise;
11 | }
12 |
13 | export const labelUniDriverFactory = (base: UniDriver): LabelDriver => {
14 |
15 | return {
16 | ...coreLabelUniDriverFactory(base),
17 | getSize: () => base.attr('data-size') as Promise
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/Label/constants.ts:
--------------------------------------------------------------------------------
1 | export type Size = 'small' | 'medium';
2 |
3 | export enum SIZES {
4 | small = 'small',
5 | medium = 'medium'
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Label/index.ts:
--------------------------------------------------------------------------------
1 | import {Label as LabelComponent} from './Label';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const Label = createHOC(LabelComponent);
5 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/LabelWithOptions.driver.ts:
--------------------------------------------------------------------------------
1 | export {labelWithOptionsDriverFactory} from 'wix-ui-core/drivers/vanilla';
2 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/LabelWithOptions.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
3 | import {labelWithOptionsTestkitFactory} from '../../testkit/protractor';
4 | import {browser} from 'protractor';
5 |
6 | describe('LabelWithOptions', () => {
7 | const storyUrl = getStoryUrl('Components', 'LabelWithOptions');
8 | const dataHook = 'storybook-labelwithoptions';
9 |
10 | beforeEach(() => browser.get(storyUrl));
11 |
12 | eyes.it('should render LabelWithOptions', async () => {
13 | const driver = labelWithOptionsTestkitFactory({dataHook});
14 | await waitForVisibilityOf(driver.element(), 'Cannot find LabelWithOptions');
15 | expect(driver.element()).toBeDefined();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/LabelWithOptions.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {labelWithOptionsDriverFactory, LabelWithOptionsDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/LabelWithOptions.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {createDriverFactory} from 'wix-ui-test-utils/driver-factory';
3 | import {labelWithOptionsDriverFactory} from './LabelWithOptions.driver';
4 | import {LabelWithOptions} from '.';
5 | import {labelWithOptionsTestkitFactory} from '../../testkit';
6 | import {labelWithOptionsTestkitFactory as enzymeLabelWithOptionsTestkitFactory} from '../../testkit/enzyme';
7 | import {isEnzymeTestkitExists} from 'wix-ui-test-utils/enzyme';
8 | import {isTestkitExists} from 'wix-ui-test-utils/vanilla';
9 | import {mount} from 'enzyme';
10 |
11 | describe('LabelWithOptions', () => {
12 | const createDriver = createDriverFactory(labelWithOptionsDriverFactory);
13 |
14 | it('should render LabelWithOptions', () => {
15 | const driver = createDriver();
16 | expect(driver.isTargetElementExists()).toBeTruthy();
17 | expect(driver.isContentElementExists()).toBeFalsy();
18 | });
19 |
20 | describe('testkit', () => {
21 | it('should exist', () => {
22 | expect(isTestkitExists(, labelWithOptionsTestkitFactory)).toBe(true);
23 | });
24 | });
25 |
26 | describe('enzyme testkit', () => {
27 | it('should exist', () => {
28 | expect(isEnzymeTestkitExists(, enzymeLabelWithOptionsTestkitFactory, mount)).toBe(true);
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/LabelWithOptions.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | LabelWithOptions as CoreLabelWithOptions,
4 | LabelWithOptionsProps as CoreLabelWithOptionsProps
5 | } from 'wix-ui-core/dist/src/components/label-with-options';
6 | import { withStylable } from 'wix-ui-core/dist/src/utils/withStylable';
7 | import ChevronDown from 'wix-ui-icons-common/ChevronDown';
8 | import style from './LabelWithOptions.st.css';
9 | import { Tooltip } from '../Tooltip';
10 | import { getInputSuffix } from '../Input/InputSuffixes';
11 | import FormFieldError from 'wix-ui-icons-common/system/FormFieldError';
12 |
13 | export interface LabelWithOptionsProps {
14 | // The size of the LabelWithOptions
15 | size?: 'large' | 'medium' | 'small';
16 | }
17 |
18 | const defaultProps = {
19 | size: 'medium'
20 | };
21 |
22 | const StyledLabelWithOptions = withStylable<
23 | CoreLabelWithOptionsProps,
24 | LabelWithOptionsProps
25 | >(CoreLabelWithOptions, style, ({ size }) => ({ size }), defaultProps);
26 |
27 | export type LabelWithOptionsType = React.SFC<
28 | CoreLabelWithOptionsProps & LabelWithOptionsProps
29 | > & {
30 | createOption: typeof CoreLabelWithOptions.createOption;
31 | createDivider: typeof CoreLabelWithOptions.createDivider;
32 | };
33 |
34 | const defaultSuffix = ;
35 | const renderSuffix = ({ isError, disabled }) =>
36 | getInputSuffix({
37 | error: isError ? 'Selection is required!' : null,
38 | disabled,
39 | suffix: defaultSuffix
40 | });
41 |
42 | export const LabelWithOptions: LabelWithOptionsType = ((
43 | props: CoreLabelWithOptionsProps & LabelWithOptionsProps
44 | ) => {
45 | const { disabled } = props;
46 | return (
47 | renderSuffix({ isError, disabled })}
49 | {...props}
50 | />
51 | );
52 | }) as LabelWithOptionsType;
53 |
54 | LabelWithOptions.displayName = 'LabelWithOptions';
55 | LabelWithOptions.createOption = CoreLabelWithOptions.createOption;
56 | LabelWithOptions.createDivider = CoreLabelWithOptions.createDivider;
57 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/index.ts:
--------------------------------------------------------------------------------
1 | export {LabelWithOptions} from './LabelWithOptions';
2 |
--------------------------------------------------------------------------------
/src/components/LabelWithOptions/readme.md:
--------------------------------------------------------------------------------
1 | # ``
2 |
3 | A dropdown like component, where trigger is text
4 |
5 | ```js
6 | import {LabelWithOptions} from 'wix-ui-backoffice/LabelWithOptions';
7 |
8 | const options = [
9 | LabelWithOptions.createOption({value: `value0`}), // generates an option with a unique id
10 | LabelWithOptions.createOption({id: 1, value: `value1`}), // generates an option with id, value
11 | LabelWithOptions.createOption({id: 2, value: `value2`, isDisabled: true}), // genrates a disabled option
12 | LabelWithOptions.createOption({id: 3, value: `value3`, isSelectable: false}), // generates an unselectable option
13 | LabelWithOptions.createOption({id: 4, value: `value4`, render: value => value + 's'}), // generates an option with a custom render function
14 | LabelWithOptions.createDivider(), // generates default divider
15 | LabelWithOptions.createDivider('Value') // generates a divider with value
16 | ];
17 |
18 | null}
21 | onDeselect={option => null}
22 | initialSelectedIds={null || [1]}
23 | fixedHeader={'Fixed Header'}
24 | fixedFooter={'Fixed Footer'}
25 | disabled={false}
26 | placeholder={'This is a placeholder'}
27 | required={false}
28 | size={'large' || 'medium' || 'small'}
29 | />
30 | ```
31 |
--------------------------------------------------------------------------------
/src/components/LinearProgressBar/LinearProgressBar.driver.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFactory } from 'wix-ui-test-utils/driver-factory';
2 | import {
3 | linearProgressBarDriverFactory as coreLinearProgressBarDriverFactory,
4 | LinearProgressBarDriver as CoreLinearProgressBarDriver
5 | } from 'wix-ui-core/drivers/vanilla';
6 | import { BaseDriver, DriverFactory } from 'wix-ui-test-utils/driver-factory';
7 | import { tooltipDriverFactory } from '../Tooltip/Tooltip.driver'
8 |
9 | export interface LinearProgressBarDriver extends CoreLinearProgressBarDriver {
10 | /* Returns true if the tooltip is shown */
11 | isTooltipShown: () => boolean;
12 | /* Returns true if the error icon is shown */
13 | isErrorIconShown: () => boolean;
14 | /* Returns true if the success icon is shown */
15 | isSuccessIconShown: () => boolean;
16 | /* Returns the tooltip driver */
17 | getTooltip: () => any;
18 |
19 | }
20 |
21 | export const linearProgressBarDriverFactory: DriverFactory = ({ element, eventTrigger, wrapper }: ComponentFactory): LinearProgressBarDriver => {
22 | const createTooltipDriver = () => tooltipDriverFactory({ element: element.querySelector(`[data-hook='linear-progressbar-tooltip']`), wrapper, eventTrigger });
23 | const coreProgressBarDriver = coreLinearProgressBarDriverFactory({ element, wrapper, eventTrigger });
24 | const errorIcon = () => element.querySelector(`[data-hook='error-icon']`);
25 | const successIcon = () => element.querySelector(`[data-hook='success-icon']`);
26 |
27 | return {
28 | ...coreProgressBarDriver,
29 | isTooltipShown: () => createTooltipDriver().isContentElementExists(),
30 | getTooltip: () => createTooltipDriver(),
31 | isErrorIconShown: () => !!errorIcon(),
32 | isSuccessIconShown: () => !!successIcon()
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/LinearProgressBar/LinearProgressBar.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {$, browser} from 'protractor';
3 | import * as autoExampleDriver from 'wix-storybook-utils/AutoExampleDriver';
4 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
5 | import {linearProgressBarTestkitFactory, LinearProgressBarDriver} from '../../testkit/protractor';
6 | import {enumValues} from '../../utils';
7 |
8 | describe('LinearProgressBar', () => {
9 | const storyUrl = getStoryUrl('Components', 'LinearProgressBar');
10 | let driver: LinearProgressBarDriver;
11 |
12 | beforeAll(async () => {
13 | await browser.get(storyUrl);
14 | driver = linearProgressBarTestkitFactory({dataHook: 'linear-progress-bar-story'});
15 | await waitForVisibilityOf(driver.element(), 'Cannot find LinearProgressBar');
16 | });
17 |
18 | afterEach(() => autoExampleDriver.reset());
19 |
20 | eyes.it('should exist', () => {
21 | expect(driver.element().isPresent()).toBe(true);
22 | });
23 |
24 | eyes.it('should render correct success state', async () => {
25 | await autoExampleDriver.setProps({value: 100, showProgressIndication: true});
26 | expect(driver.element().isPresent()).toBe(true);
27 | });
28 |
29 | eyes.it('should render correct error state', async () => {
30 | await autoExampleDriver.setProps({value: 30, showProgressIndication: true, error: true, errorMessage: 'Some error'});
31 | expect(driver.element().isPresent()).toBe(true);
32 |
33 | eyes.checkWindow('errorIcon');
34 |
35 | driver.showError();
36 |
37 | await waitForVisibilityOf($(`[data-hook="linear-progressbar-tooltip"]`), 'Cannot find CircularProgressBar tooltip');
38 | });
39 |
40 | eyes.it('should render correct light state', async () => {
41 | await autoExampleDriver.setProps({value: 20, light: true});
42 | expect(driver.element().isPresent()).toBe(true);
43 |
44 | eyes.checkWindow('light');
45 |
46 | await autoExampleDriver.setProps({value: 20, light: true, error: true});
47 | expect(driver.element().isPresent()).toBe(true);
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/src/components/LinearProgressBar/LinearProgressBar.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | import {promise, browser, $, ElementFinder} from 'protractor';
2 | import {DriverFactory} from 'wix-ui-core/dist/src/common/BaseDriver.protractor';
3 | import {linearProgressBarDriverFactory as coreLinearProgressBarDriverFactory, LinearProgressBarDriver as CoreLinearProgressBarDriver} from 'wix-ui-core/drivers/protractor';
4 |
5 | export interface LinearProgressBarDriver extends CoreLinearProgressBarDriver {
6 | /** Hovers over the error icon to display the tooltip with the error message */
7 | showError: () => promise.Promise;
8 | }
9 |
10 | export const linearProgressBarDriverFactory: DriverFactory = (element: ElementFinder): LinearProgressBarDriver => {
11 | const errorIcon = () => element.$(`[data-hook='error-icon']`);
12 | return {
13 | ...coreLinearProgressBarDriverFactory(element),
14 | showError: () => browser.actions().mouseMove(errorIcon()).perform()
15 | };
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/LinearProgressBar/LinearProgressBar.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: LinearProgressBar;
4 | }
5 |
6 | :import {
7 | -st-from: "../../typography.st.css";
8 | -st-named: fontMedium;
9 | }
10 |
11 | :import {
12 | -st-from: "../../colors.st.css";
13 | -st-named:
14 | B00, B10, B30,
15 | D20,
16 | R00, R10, R30,
17 | WHITE,
18 | }
19 |
20 | .root {
21 | -st-states: light;
22 | -st-extends: LinearProgressBar;
23 | padding: 0px 6px;
24 | height: 30px;
25 | }
26 |
27 | .root::barForeground {
28 | background: value(B00);
29 | transition: width 0.5s ease-in-out;
30 | }
31 |
32 | .root::barBackground {
33 | background: value(B30);
34 | }
35 |
36 | .root::barBackground,
37 | .root::barForeground
38 | {
39 | border-radius: 2px;
40 | height: 4px;
41 | }
42 |
43 | .root:error::barForeground {
44 | background: value(R00);
45 | }
46 |
47 | .root:error::barBackground {
48 | background: value(R30);
49 | }
50 |
51 | .root:light::barBackground {
52 | background: value(WHITE);
53 | }
54 |
55 | .root::progressIndicationSection {
56 | margin-left: 18px;
57 | }
58 |
59 | :global([dir="rtl"]) .root::progressIndicationSection {
60 | margin-right: 18px;
61 | margin-left: 0;
62 | }
63 |
64 | .root::indicationContainer {
65 | width: 18px;
66 | height: 18px;
67 | border-radius: 12px;
68 | display: flex;
69 | justify-content: center;
70 | align-items: center;
71 | color: value(D20);
72 | font-size: 10px;
73 | font-family: value(fontMedium);
74 | }
75 |
76 | .root:success::indicationContainer {
77 | background: value(B10);
78 | }
79 |
80 | .root:error::indicationContainer {
81 | background: value(R10);
82 | }
83 |
84 | .root::indicationContainer svg {
85 | height: 8px;
86 | width: 10px;
87 | color: value(WHITE);
88 | }
89 |
--------------------------------------------------------------------------------
/src/components/LinearProgressBar/LinearProgressBar.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | LinearProgressBar as CoreLinearProgressBar,
4 | LinearProgressBarProps as CoreLinearProgressBarProps
5 | } from 'wix-ui-core/linear-progress-bar';
6 | import ToggleOn from 'wix-ui-icons-common/system/ToggleOn';
7 | import FormFieldError from 'wix-ui-icons-common/system/FormFieldError';
8 | import style from './LinearProgressBar.st.css';
9 | import { Tooltip } from '../Tooltip';
10 | import { Omit } from '../../types/common';
11 |
12 | export interface LinearProgressBarProps
13 | extends Omit {
14 | /** message to display when an error happens */
15 | errorMessage?: string;
16 | /** use light theme instead of dark theme */
17 | light?: boolean;
18 | }
19 |
20 | export const LinearProgressBar: React.SFC = (
21 | props: LinearProgressBarProps
22 | ) => {
23 | const { errorMessage, light, ...otherProps } = props;
24 |
25 | return (
26 | }
30 | errorIcon={
31 |
36 |
37 |
38 | }
39 | />
40 | );
41 | };
42 |
43 | LinearProgressBar.displayName = 'LinearProgressBar';
44 |
--------------------------------------------------------------------------------
/src/components/LinearProgressBar/index.ts:
--------------------------------------------------------------------------------
1 | import {LinearProgressBar as LinearProgressBarComponent} from './LinearProgressBar';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const LinearProgressBar = createHOC(LinearProgressBarComponent);
5 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/CounterBadge.driver.ts:
--------------------------------------------------------------------------------
1 | import { Skin } from './constants';
2 | import { ComponentFactory, BaseDriver } from 'wix-ui-test-utils/driver-factory';
3 | import { badgeDriverFactory as coreBadgeDriverFactory, BadgeDriver as CoreBadgeDriver } from 'wix-ui-core/drivers/vanilla';
4 | import { StylableDOMUtil } from '@stylable/dom-test-kit';
5 | import style from './CounterBadge.st.css';
6 |
7 | export interface CounterBadgeDriver extends CoreBadgeDriver {
8 | /** returns the skin color */
9 | getSkin: () => Skin | null;
10 | /** checks if the component is in wide mode */
11 | isWide: () => boolean;
12 | /** returns the icon if provided */
13 | getIcon: () => Element | null;
14 | }
15 |
16 | export const counterBadgeDriverFactory = (factoryParams: ComponentFactory): CounterBadgeDriver => {
17 | const coreBadgeDriver = coreBadgeDriverFactory(factoryParams);
18 | const { element } = factoryParams;
19 | const stylableDOMUtil = new StylableDOMUtil(style, element);
20 |
21 | return {
22 | ...coreBadgeDriver,
23 | getSkin: () => stylableDOMUtil.getStyleState(element, 'skin') as Skin | null,
24 | isWide: () => stylableDOMUtil.hasStyleState(element, 'wide'),
25 | getIcon: () => stylableDOMUtil.select('.icon')
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/CounterBadge.e2e.tsx:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import { browser } from 'protractor';
3 | import { getStoryUrl, waitForVisibilityOf } from 'wix-ui-test-utils/protractor';
4 | import { stylableCounterBadgeTestkitFactory as counterBadgeTestkitFactory } from '../../testkit/protractor';
5 |
6 | describe('CounterBadge', () => {
7 | const storyUrl = getStoryUrl('Components', 'StylableCounterBadge');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should display correct content', () => {
11 | const dataHook = 'storybook-counterBadge';
12 | const driver = counterBadgeTestkitFactory({ dataHook });
13 |
14 | return waitForVisibilityOf(
15 | driver.element(),
16 | 'Cannot find CounterBadge'
17 | ).then(() => expect(driver.text()).toBe('12'));
18 | });
19 |
20 | eyes.it('should display "99+" when number > 99', () => {
21 | const dataHook = 'storybook-counterBadge';
22 | const driver = counterBadgeTestkitFactory({ dataHook });
23 |
24 | return waitForVisibilityOf(
25 | driver.element(),
26 | 'Cannot find CounterBadge'
27 | ).then(() => expect(driver.text()).toBe('99+'));
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/CounterBadge.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {badgeDriverFactory as counterBadgeDriverFactory, BadgeDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/CounterBadge.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: BadgeStyle;
4 | }
5 |
6 | :import {
7 | -st-from: "wix-ui-core/index.st.css";
8 | -st-named: Badge;
9 | }
10 |
11 | :import {
12 | -st-from: "../../typography.st.css";
13 | -st-named: fontMedium;
14 | }
15 |
16 | :import {
17 | -st-from: "../../colors.st.css";
18 | -st-named:
19 | B10,
20 | D20,
21 | G10,
22 | O10,
23 | R10,
24 | Y10,
25 | WHITE;
26 | }
27 |
28 | .root {
29 | -st-extends: Badge;
30 | -st-states: skin(string), wide;
31 | }
32 |
33 | .text {
34 | font-family: value(fontMedium);
35 | font-size: 10px;
36 | line-height: 12px;
37 | letter-spacing: 0;
38 | color: currentColor;
39 | text-transform: uppercase;
40 | }
41 |
42 | .icon {
43 | width: 12px;
44 | height: 12px;
45 | }
46 |
47 | .root:skin(general) {
48 | -st-mixin: BadgeStyle(
49 | backgroundColor value(D20),
50 | borderColor value(D20)
51 | );
52 | }
53 |
54 | .root:skin(standard) {
55 | -st-mixin: BadgeStyle(
56 | backgroundColor value(B10),
57 | borderColor value(B10)
58 | );
59 | }
60 |
61 | .root:skin(danger) {
62 | -st-mixin: BadgeStyle(
63 | backgroundColor value(R10),
64 | borderColor value(R10)
65 | );
66 | }
67 |
68 | .root:skin(warning) {
69 | -st-mixin: BadgeStyle(
70 | backgroundColor value(Y10),
71 | borderColor value(Y10)
72 | );
73 | }
74 |
75 | .root:skin(urgent) {
76 | -st-mixin: BadgeStyle(
77 | backgroundColor value(O10),
78 | borderColor value(O10)
79 | );
80 | }
81 |
82 | .root:skin(success) {
83 | -st-mixin: BadgeStyle(
84 | backgroundColor value(G10),
85 | borderColor value(G10)
86 | );
87 | }
88 |
89 | .root:skin(general),
90 | .root:skin(standard),
91 | .root:skin(danger),
92 | .root:skin(warning),
93 | .root:skin(urgent),
94 | .root:skin(success) {
95 | min-width: 18px;
96 | border-radius: 12px;
97 | border: initial;
98 | height: 18px;
99 | padding: 2px;
100 | }
101 |
102 | .root:wide {
103 | padding: 2px 6px;
104 | }
105 |
106 | .root:wide .text {
107 | letter-spacing: 1px;
108 | }
109 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/CounterBadge.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { withStylable } from 'wix-ui-core/dist/src/utils/withStylable';
3 | import {
4 | Badge as CoreBadge,
5 | BadgeProps as CoreBadgeProps
6 | } from 'wix-ui-core/dist/src/components/deprecated/stylable-badge';
7 | import { Skin, SKIN, maxNumberBeforeTruncation } from './constants';
8 | import { isIcon, isWide } from './utils';
9 | import style from './CounterBadge.st.css';
10 |
11 | export type Content = string | number | React.ReactElement;
12 |
13 | export interface CounterBadgeProps {
14 | /** Skin of the badge */
15 | skin?: Skin;
16 |
17 | /** Content of the badge */
18 | children?: Content;
19 | }
20 |
21 | const defaultProps: CounterBadgeProps = {
22 | skin: SKIN.general,
23 | children: ''
24 | };
25 |
26 | type CounterBadgeExtendedProps = CounterBadgeProps & { wide: boolean };
27 | const getState = ({ skin, wide }) => ({ skin, wide });
28 |
29 | const StyledCounterBadge = withStylable<
30 | CoreBadgeProps,
31 | CounterBadgeExtendedProps
32 | >(CoreBadge, style, getState, defaultProps);
33 |
34 | export class CounterBadge extends React.PureComponent {
35 | static displayName = 'CounterBadge';
36 |
37 | static defaultProps = defaultProps;
38 |
39 | private readonly getContent = () => {
40 | const { children } = this.props;
41 | const isChildrenIcon = isIcon(children);
42 | let content = children;
43 |
44 | if (!isChildrenIcon && Number(children) > maxNumberBeforeTruncation) {
45 | content = '99+';
46 | }
47 |
48 | return isChildrenIcon ? (
49 | React.cloneElement(children as React.ReactElement, {
50 | className: style.icon
51 | })
52 | ) : (
53 | {content}
54 | );
55 | };
56 |
57 | render() {
58 | const { children, ...rest } = this.props;
59 |
60 | return (
61 |
62 | {this.getContent()}
63 |
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/constants.ts:
--------------------------------------------------------------------------------
1 | export type Skin = 'general' | 'standard' | 'danger' | 'warning' | 'urgent' | 'success';
2 |
3 | export enum SKIN {
4 | general = 'general',
5 | standard = 'standard',
6 | danger = 'danger',
7 | warning = 'warning',
8 | urgent = 'urgent',
9 | success = 'success'
10 | }
11 |
12 | export const maxContentLength = 2;
13 |
14 | export const maxNumberBeforeTruncation = 99;
15 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/index.ts:
--------------------------------------------------------------------------------
1 | import {CounterBadge as CounterBadgeComponent} from './CounterBadge';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const CounterBadge = createHOC(CounterBadgeComponent);
5 |
--------------------------------------------------------------------------------
/src/components/StylableCounterBadge/utils.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {maxContentLength} from './constants';
3 |
4 | export const getContent = children => React.Children.toArray(children)[0];
5 |
6 | export const isIcon = children => typeof children !== 'string' && typeof children !== 'number';
7 |
8 | export const isWide = children => {
9 | const content = getContent(children);
10 |
11 | if (isIcon(children)) {
12 | return false;
13 | }
14 |
15 | const contentLength = content.toString().length;
16 |
17 | return contentLength >= maxContentLength;
18 | };
19 |
--------------------------------------------------------------------------------
/src/components/Text/README.md:
--------------------------------------------------------------------------------
1 | # ``
2 |
3 | General text component with Wix styling.
4 |
5 | ## Usage
6 |
7 | 1. Load Wix fonts from CDN:
8 |
9 | ```html
10 |
11 | ```
12 |
13 | 2. Use `` component with appropriate appearance:
14 |
15 | ```js
16 | import {Text} from 'wix-ui-backoffice/Text';
17 |
18 | const Component = () =>
19 |
20 | Some Text
21 |
;
22 | ```
23 |
--------------------------------------------------------------------------------
/src/components/Text/Text.driver.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFactory } from 'wix-ui-test-utils/driver-factory';
2 | import { textDriverFactory as coreTextDriverFactory, TextDriver as CoreTextDriver } from '../core/CoreText/Text.driver';
3 | import { StylableDOMUtil } from '@stylable/dom-test-kit';
4 | import style from './Text.st.css';
5 | import { Skin, Size } from './constants';
6 |
7 | export interface TextDriver extends CoreTextDriver {
8 | getSize: () => Size,
9 | getSkin: () => Skin,
10 | isLight: () => boolean,
11 | isBold: () => boolean,
12 | isSecondary: () => boolean
13 | }
14 |
15 | export const textDriverFactory = ({ element, eventTrigger, wrapper }: ComponentFactory): TextDriver => {
16 | const coreTextDriver = coreTextDriverFactory({ element, eventTrigger, wrapper });
17 | const stylableDOMUtil = new StylableDOMUtil(style);
18 |
19 | return {
20 | ...coreTextDriver,
21 | getSize: () => stylableDOMUtil.getStyleState(element, 'size'),
22 | getSkin: () => stylableDOMUtil.getStyleState(element, 'skin'),
23 | isLight: () => stylableDOMUtil.hasStyleState(element, 'light'),
24 | isBold: () => stylableDOMUtil.hasStyleState(element, 'bold'),
25 | isSecondary: () => stylableDOMUtil.hasStyleState(element, 'secondary')
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/src/components/Text/Text.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {textTestkitFactory} from '../../testkit/protractor';
5 |
6 | describe('Text', () => {
7 | const storyUrl = getStoryUrl('Components', 'Text');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should display correct content', () => {
11 | const dataHook = 'storybook-text';
12 | const driver = textTestkitFactory({dataHook});
13 |
14 | return waitForVisibilityOf(driver.element(), 'Cannot find Heading')
15 | .then(() => expect(driver.getText()).toBe('Some text'));
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/components/Text/Text.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {textDriverFactory, TextDriver} from '../core/CoreText/Text.protractor.driver';
2 |
--------------------------------------------------------------------------------
/src/components/Text/Text.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "../core/CoreText/Text.st.css";
3 | -st-default: Text;
4 | }
5 |
6 | :import {
7 | -st-from: "../../colors.st.css";
8 | -st-named:
9 | D10, D20, D50,
10 | G10,P10,
11 | R10,
12 | WHITE,
13 | }
14 |
15 | :import {
16 | -st-from: "../../typography.st.css";
17 | -st-named: fontLight, fontRoman;
18 | }
19 |
20 | .root {
21 | -st-extends: Text;
22 | -st-states:
23 | size(enum(small, medium)),
24 | secondary,
25 | skin(enum(standard, success, error, premium)),
26 | light,
27 | bold;
28 |
29 | font-family: value(fontLight);
30 | }
31 |
32 | .root:not(:ellipsis) {
33 | white-space: pre-line;
34 | }
35 |
36 | .root:size(medium), .root:size(medium):secondary {
37 | font-size: 16px;
38 | line-height: 24px;
39 | }
40 |
41 | .root:size(small), .root:size(small):secondary {
42 | font-size: 14px;
43 | line-height: 18px;
44 | }
45 |
46 | .root:size(medium), .root:size(small) {
47 | color: value(D10);
48 | }
49 |
50 | .root:size(medium):light, .root:size(small):light {
51 | color: value(WHITE);
52 | }
53 |
54 | .root:size(medium):secondary, .root:size(small):secondary {
55 | color: value(D20);
56 | }
57 |
58 | .root:size(medium):secondary:light, .root:size(small):secondary:light {
59 | color: value(D50);
60 | }
61 |
62 | .root:skin(success),
63 | .root:skin(success):light,
64 | .root:skin(success):secondary {
65 | color: value(G10);
66 | }
67 |
68 | .root:skin(error),
69 | .root:skin(error):light,
70 | .root:skin(error):secondary {
71 | color: value(R10);
72 | }
73 |
74 | .root:skin(premium),
75 | .root:skin(premium):light,
76 | .root:skin(premium):secondary {
77 | color: value(P10);
78 | }
79 |
80 | .root:bold {
81 | font-family: value(fontRoman);
82 | }
--------------------------------------------------------------------------------
/src/components/Text/Text.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {Text as CoreText, TextProps as CoreTextProps} from '../core/CoreText';
3 | import {withStylable} from 'wix-ui-core/dist/src/utils/withStylable';
4 | import {Skin, Size} from './constants';
5 | import style from './Text.st.css';
6 |
7 | export interface Props {
8 | /** font size of the text */
9 | size?: Size;
10 |
11 | /** is the text type is secondary. Affects the font color */
12 | secondary?: boolean;
13 |
14 | /** skin color of the text */
15 | skin?: Skin;
16 |
17 | /** is the text has dark or light skin */
18 | light?: boolean;
19 |
20 | /** is the text bold */
21 | bold?: boolean;
22 | }
23 |
24 | const defaultProps: Props = {
25 | size: Size.medium,
26 | secondary: false,
27 | skin: Skin.standard,
28 | light: false,
29 | bold: false
30 | };
31 |
32 | export const Text = withStylable(
33 | CoreText,
34 | style,
35 | ({size, secondary, skin, light, bold}) => ({
36 | size,
37 | secondary,
38 | skin,
39 | light: light && skin === Skin.standard,
40 | bold
41 | }),
42 | defaultProps
43 | );
44 |
45 | Text.displayName = 'Text';
46 |
--------------------------------------------------------------------------------
/src/components/Text/constants.ts:
--------------------------------------------------------------------------------
1 | export enum Skin {
2 | standard = 'standard',
3 | error = 'error',
4 | success = 'success',
5 | premium = 'premium'
6 | }
7 |
8 | export enum Size {
9 | small = 'small',
10 | medium = 'medium'
11 | }
12 |
--------------------------------------------------------------------------------
/src/components/Text/index.ts:
--------------------------------------------------------------------------------
1 | import { Text as TextComponent , Props } from './Text';
2 | import { createHOC } from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const Text = createHOC(TextComponent);
5 | export { Props as TextProps }
6 | export { Skin as TextSkin, Size as TextSize } from './constants';
--------------------------------------------------------------------------------
/src/components/Thumbnail/Thumbnail.driver.ts:
--------------------------------------------------------------------------------
1 | import {ComponentFactory} from 'wix-ui-test-utils/driver-factory';
2 | import {thumbnailDriverFactory as coreTuhmbnailDriverFactory, ThumbnailDriver as CoreThumbnailDriver} from 'wix-ui-core/drivers/vanilla';
3 | import {StylableDOMUtil} from '@stylable/dom-test-kit';
4 | import style from './Thumbnail.st.css';
5 | import {textDriverFactory, TextDriver} from '../Text/Text.driver';
6 | import {DriverFactory} from 'wix-ui-test-utils/driver-factory';
7 |
8 | export interface ThumbnailDriver extends CoreThumbnailDriver {
9 | titleDriver: () => TextDriver;
10 | getTitle: () => string;
11 | hasDescription: () => boolean;
12 | getDescription: () => string;
13 | hasImage: () => boolean;
14 | getImage: () => HTMLElement;
15 | }
16 |
17 | export const thumbnailDriverFactory = ({ element, eventTrigger, wrapper }: ComponentFactory): ThumbnailDriver => {
18 | const coreThumbnailDriver = coreTuhmbnailDriverFactory({element, eventTrigger, wrapper});
19 | const stylableDOMUtil = new StylableDOMUtil(style, element);
20 | const titleDriver = textDriverFactory({element: stylableDOMUtil.select('.title'), wrapper, eventTrigger});
21 | const descriptionDriver = textDriverFactory({element: stylableDOMUtil.select('.description'), wrapper, eventTrigger});
22 | const image = element.querySelector('[data-hook="image"]');
23 |
24 | return {
25 | ...coreThumbnailDriver,
26 | titleDriver: () => titleDriver,
27 | /** returns the title of the thumbnail */
28 | getTitle: () => titleDriver.getText(),
29 | /** returns true if the thumbnail has description */
30 | hasDescription: () => descriptionDriver.exists(),
31 | /** returns the description of the thumbnail */
32 | getDescription: () => descriptionDriver.getText(),
33 | /** returns the image of the thumbnail */
34 | getImage: () => image && image.childNodes[0] as HTMLElement,
35 | /** returns true if the thumbnail has an image */
36 | hasImage: () => !!image
37 | };
38 | };
39 |
--------------------------------------------------------------------------------
/src/components/Thumbnail/Thumbnail.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {thumbnailTestkitFactory} from '../../testkit/protractor';
5 |
6 | describe('Thumbnail', () => {
7 | const storyUrl = getStoryUrl('Components', 'Thumbnail');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should exist', () => {
11 | const dataHook = 'storybook-thumbnail';
12 | const driver = thumbnailTestkitFactory({dataHook});
13 |
14 | return waitForVisibilityOf(driver.element(), 'Cannot find Thumbnail')
15 | .then(() => expect(driver.element().isPresent()).toBe(true));
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/components/Thumbnail/Thumbnail.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {thumbnailDriverFactory, ThumbnailDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/Thumbnail/Thumbnail.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: Thumbnail;
4 | }
5 |
6 | :import {
7 | -st-from: "../../typography.st.css";
8 | -st-named: fontRoman;
9 | }
10 |
11 | :import {
12 | -st-from: "../../colors.st.css";
13 | -st-named:
14 | B10, B20, B50,
15 | D55,
16 | WHITE;
17 | }
18 |
19 | .root {
20 | -st-extends: Thumbnail;
21 | margin: 19px 0;
22 | border: 1px solid value(B50);
23 | border-radius: 8px;
24 | cursor: pointer;
25 | }
26 |
27 | .root:selected {
28 | border: 2px solid value(B10);
29 | }
30 |
31 | .root:selected:hover {
32 | border: 2px solid value(B20);
33 | }
34 |
35 | .root:selected:disabled {
36 | border: 2px solid value(D55);
37 | }
38 |
39 | .root:disabled {
40 | border: 1px solid value(D55);
41 | cursor: default;
42 | }
43 |
44 | .container {
45 | display: flex;
46 | flex-direction: column;
47 | align-items: center;
48 | }
49 |
50 | .root:selected::selectedIcon {
51 | background: value(B10);
52 | width: 24px;
53 | height: 24px;
54 | border-radius: 12px;
55 | display: flex;
56 | justify-content: center;
57 | align-items: center;
58 | color: value(WHITE);
59 | }
60 |
61 | .root:selected:hover:not(:disabled)::selectedIcon {
62 | background: value(B20);
63 | }
64 |
65 | .root:disabled::selectedIcon {
66 | background: value(D55);
67 | }
68 |
69 | .title {}
70 |
71 | .description {}
72 |
73 | .root:disabled .title, .root:disabled .description {
74 | color: value(D55);
75 | }
76 |
--------------------------------------------------------------------------------
/src/components/Thumbnail/Thumbnail.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import style from './Thumbnail.st.css';
3 | import Check from 'wix-ui-icons-common/Check';
4 | import {
5 | Thumbnail as CoreThumbnail,
6 | ThumbnailProps as CoreThumbnailProps
7 | } from 'wix-ui-core/dist/src/components/thumbnail';
8 | import { withStylable } from 'wix-ui-core/dist/src/utils/withStylable';
9 | import { Text } from '../Text';
10 |
11 | export interface ThumbnailProps extends CoreThumbnailProps {
12 | /** image of the thumbnail */
13 | image?: React.ReactElement;
14 | /** title of the thumbnail */
15 | title: string;
16 | /** description of the thumbnail */
17 | description?: string;
18 | }
19 |
20 | const StyledThumbnail = withStylable(
21 | CoreThumbnail,
22 | style,
23 | () => ({})
24 | );
25 |
26 | export const Thumbnail: React.SFC = props => {
27 | const { children, title, image, description, ...rest } = props;
28 |
29 | return (
30 | }>
31 |
32 | {image &&
{image}
}
33 |
34 | {title}
35 |
36 | {description && (
37 |
38 | {description}
39 |
40 | )}
41 |
42 |
43 | );
44 | };
45 |
46 | Thumbnail.displayName = 'Thumbnail';
47 |
--------------------------------------------------------------------------------
/src/components/Thumbnail/index.ts:
--------------------------------------------------------------------------------
1 | export {Thumbnail, ThumbnailProps} from './Thumbnail';
2 |
--------------------------------------------------------------------------------
/src/components/TimePicker/TimePicker.driver.ts:
--------------------------------------------------------------------------------
1 | import {
2 | timePickerDriverFactory as coreTimePickerDriverFactory
3 | } from 'wix-ui-core/drivers/vanilla';
4 |
5 | export const timePickerDriverFactory = ({element, eventTrigger}) => {
6 | const coreTimePickerDriver = coreTimePickerDriverFactory({element, eventTrigger});
7 |
8 | return {
9 | ...coreTimePickerDriver,
10 | getValue: () => coreTimePickerDriver.getValue().slice(0, 5),
11 | isAmPmIndicatorExist: () => {
12 | const value = coreTimePickerDriver.getValue().toLowerCase();
13 | return value.includes('am') || value.includes('pm');
14 | },
15 | getAmPmIndicatorText: () => coreTimePickerDriver.getValue().toLowerCase().slice(6, 8)
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/src/components/TimePicker/TimePicker.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {timePickerDriverFactory, TimePickerDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/TimePicker/TimePicker.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: TimePicker;
4 | }
5 |
6 | :import {
7 | -st-from: "../Input/Input.st.css";
8 | -st-default: Input;
9 | }
10 |
11 | :import {
12 | -st-from: "../Input/InputStates.st.css";
13 | -st-named: input-large, input-medium, input-small;
14 | }
15 |
16 | :import {
17 | -st-from: "../../colors.st.css";
18 | -st-named:
19 | B30, B10, D55;
20 | }
21 |
22 | .root {
23 | -st-extends: TimePicker;
24 | -st-mixin: Input;
25 | -st-states: disabled, size(enum(large, medium, small)),
26 | inputWidth(enum(small, medium, large, small_ampm, medium_ampm, large_ampm));
27 |
28 | display: inline-flex;
29 | width: auto;
30 | }
31 |
32 | .root:size(large) {
33 | -st-mixin: input-large;
34 | }
35 |
36 | .root:size(medium) {
37 | -st-mixin: input-medium;
38 | }
39 |
40 | .root:size(small) {
41 | -st-mixin: input-small;
42 | }
43 |
44 | .root::nativeInput::selection {
45 | background: value(B30);
46 | }
47 |
48 | .root:inputWidth(small)::nativeInput {
49 | width: 47px;
50 | }
51 |
52 | .root:inputWidth(medium)::nativeInput {
53 | width: 53px;
54 | }
55 |
56 | .root:inputWidth(large)::nativeInput {
57 | width: 67px;
58 | }
59 |
60 | .root:inputWidth(small_ampm)::nativeInput {
61 | width: 72px;
62 | }
63 |
64 | .root:inputWidth(medium_ampm)::nativeInput {
65 | width: 80px;
66 | }
67 |
68 | .root:inputWidth(large_ampm)::nativeInput {
69 | width: 107px;
70 | }
71 |
72 | .root::tickers {
73 | padding: 0 6px 0 12px;
74 | }
75 |
76 | .root::tickers::ticker {
77 | padding: 5px 0;
78 | color: value(B10);
79 | cursor: pointer;
80 | }
81 |
82 | .root::tickers::ticker > svg {
83 | display: block;
84 | width: 10px;
85 | height: 5px;
86 | }
87 |
88 | .root:disabled::tickers::ticker {
89 | cursor: default;
90 | color: value(D55);
91 | }
92 |
--------------------------------------------------------------------------------
/src/components/TimePicker/constants.ts:
--------------------------------------------------------------------------------
1 | export enum Size {
2 | large = 'large',
3 | medium = 'medium',
4 | small = 'small',
5 | }
6 |
--------------------------------------------------------------------------------
/src/components/TimePicker/index.ts:
--------------------------------------------------------------------------------
1 | import {TimePicker as TimePickerComponent} from './TimePicker';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const TimePicker = createHOC(TimePickerComponent);
5 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/ToggleSwitch.driver.ts:
--------------------------------------------------------------------------------
1 | import {toggleSwitchDriverFactory as coreToggleSwitchDriverFactory} from 'wix-ui-core/drivers/vanilla';
2 | import {StylableDOMUtil} from '@stylable/dom-test-kit';
3 | import style from './ToggleSwitch.st.css';
4 |
5 | export const toggleSwitchDriverFactory = ({element, eventTrigger}) => {
6 | const coreToggleSwitchDriver = coreToggleSwitchDriverFactory({element, eventTrigger});
7 | const stylableDOMUtil = new StylableDOMUtil(style, element);
8 |
9 | return {
10 | ...coreToggleSwitchDriver,
11 | getSize: () => stylableDOMUtil.getStyleState(element, 'size'),
12 | getSkin: () => stylableDOMUtil.getStyleState(element, 'skin')
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/ToggleSwitch.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {toggleSwitchTestkitFactory} from '../../testkit/protractor';
5 | import {protractor} from 'protractor';
6 |
7 | describe('ToggleSwitch', () => {
8 | const storyUrl = getStoryUrl('Components', 'ToggleSwitch');
9 | const dataHook = 'storybook-toggleSwitch';
10 |
11 | beforeEach(() => browser.get(storyUrl));
12 |
13 | eyes.it('should toggle', () => {
14 | const driver = toggleSwitchTestkitFactory({dataHook});
15 |
16 | return waitForVisibilityOf(driver.element(), 'Cannot find ToggleSwitch')
17 | .then(() => {
18 | expect(driver.checked()).toBeFalsy();
19 |
20 | driver.click();
21 | expect(driver.checked()).toBeTruthy();
22 |
23 | driver.click();
24 | expect(driver.checked()).toBeFalsy();
25 | });
26 | });
27 |
28 | eyes.it('should support accessiblility features', () => {
29 | const driver = toggleSwitchTestkitFactory({dataHook});
30 |
31 | return waitForVisibilityOf(driver.element(), 'Cannot find ToggleSwitch')
32 | .then(() => {
33 | browser
34 | .actions()
35 | .mouseMove(driver.element())
36 | .mouseMove({x: 0, y: -20})
37 | .mouseDown()
38 | .mouseUp()
39 | .sendKeys(protractor.Key.TAB)
40 | .sendKeys(protractor.Key.SPACE)
41 | .perform();
42 |
43 | expect(driver.checked()).toBe(true);
44 |
45 | browser.actions().sendKeys(protractor.Key.SPACE).perform();
46 | expect(driver.checked()).toBe(false);
47 | });
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/ToggleSwitch.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export {toggleSwitchDriverFactory, ToggleSwitchDriver} from 'wix-ui-core/drivers/protractor';
2 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/ToggleSwitch.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: ToggleSwitch;
4 | }
5 |
6 | :import {
7 | -st-from: "wix-ui-core/index.st.css";
8 | -st-named: ToggleSwitchStyle;
9 | }
10 |
11 | :import {
12 | -st-from: "wix-ui-core/index.st.css";
13 | -st-named: ToggleSwitchLayout;
14 | }
15 |
16 | :import {
17 | -st-from: "wix-ui-core/index.st.css";
18 | -st-named: ToggleSwitchColor;
19 | }
20 |
21 | :import {
22 | -st-from: "../../colors.st.css";
23 | -st-named:
24 | B10, B20, B30, B40, B50,
25 | D50,
26 | F00,
27 | G10, G20, G30, G40,
28 | R10, R20, R30, R40,
29 | WHITE;
30 | }
31 |
32 | :import {
33 | -st-from: "../../shadows.st.css";
34 | -st-named: shadow10;
35 | }
36 |
37 | .root {
38 | -st-extends: ToggleSwitch;
39 | -st-states:
40 | size(enum(small, medium, large)),
41 | skin(enum(standard, success, error));
42 |
43 | -st-mixin: ToggleSwitchStyle;
44 | }
45 |
46 | .root:size(small) {
47 | -st-mixin: ToggleSwitchLayout(
48 | rootWidth 30px,
49 | rootHeight 16px,
50 | knobWidth 14px,
51 | knobHeight 14px
52 | );
53 | }
54 |
55 | .root:size(medium) {
56 | -st-mixin: ToggleSwitchLayout(
57 | rootWidth 36px,
58 | rootHeight 20px,
59 | knobWidth 18px,
60 | knobHeight 18px
61 | );
62 | }
63 |
64 | .root:size(large) {
65 | -st-mixin: ToggleSwitchLayout(
66 | rootWidth 48px,
67 | rootHeight 24px,
68 | knobWidth 22px,
69 | knobHeight 22px
70 | );
71 | }
72 |
73 | .root:skin(standard) {
74 | -st-mixin: ToggleSwitchColor(
75 | colorUnchecked value(B40),
76 | colorChecked value(B10),
77 | colorUncheckedHover value(B30),
78 | colorCheckedHover value(B20),
79 | colorDisabled value(D50)
80 | );
81 | }
82 |
83 | .root:skin(success) {
84 | -st-mixin: ToggleSwitchColor(
85 | colorUnchecked value(G40),
86 | colorChecked value(G10),
87 | colorUncheckedHover value(G30),
88 | colorCheckedHover value(G20),
89 | colorDisabled value(D50)
90 | );
91 | }
92 |
93 | .root:skin(error) {
94 | -st-mixin: ToggleSwitchColor(
95 | colorUnchecked value(R40),
96 | colorChecked value(R10),
97 | colorUncheckedHover value(R30),
98 | colorCheckedHover value(R20),
99 | colorDisabled value(D50)
100 | );
101 | }
102 |
103 | .root:focus-visible::track {
104 | box-shadow: 0 0 0 3px value(F00);
105 | }
106 |
107 | .root::knob {
108 | box-shadow: value(shadow10);
109 | }
110 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/ToggleSwitch.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | ToggleSwitch as CoreToggleSwitch,
4 | ToggleSwitchProps as CoreToggleSwitchProps
5 | } from 'wix-ui-core/dist/src/components/toggle-switch';
6 | import style from './ToggleSwitch.st.css';
7 | import { Skin, Size, SKINS, SIZES } from './constants';
8 | import {
9 | ToggleOff,
10 | ToggleOn,
11 | ToggleOffSmall,
12 | ToggleOnSmall
13 | } from 'wix-ui-icons-common/system';
14 | import { withStylable } from 'wix-ui-core/dist/src/utils/withStylable';
15 |
16 | export interface ToggleSwitchProps {
17 | skin?: Skin;
18 | size?: Size;
19 | }
20 |
21 | const defaultProps = {
22 | skin: SKINS.standard,
23 | size: SIZES.large
24 | };
25 |
26 | const checkedIconMap = {
27 | [SIZES.small]: undefined,
28 | [SIZES.medium]: ,
29 | [SIZES.large]:
30 | };
31 |
32 | const uncheckedIconMap = {
33 | [SIZES.small]: undefined,
34 | [SIZES.medium]: ,
35 | [SIZES.large]:
36 | };
37 |
38 | const StyledToggleSwitch = withStylable<
39 | CoreToggleSwitchProps,
40 | ToggleSwitchProps
41 | >(CoreToggleSwitch, style, ({ size, skin }) => ({ size, skin }), defaultProps);
42 |
43 | export class ToggleSwitch extends React.PureComponent<
44 | ToggleSwitchProps & CoreToggleSwitchProps
45 | > {
46 | static displayName = 'ToggleSwitch';
47 |
48 | static defaultProps = defaultProps;
49 |
50 | render() {
51 | const { styles, ...desiredProps } = this.props;
52 |
53 | return (
54 |
59 | );
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/constants.ts:
--------------------------------------------------------------------------------
1 | export type Skin = 'standard' | 'success' | 'error';
2 |
3 | export type Size = 'small' | 'medium' | 'large';
4 |
5 | export enum SKINS {
6 | standard = 'standard',
7 | success = 'success',
8 | error = 'error'
9 | }
10 |
11 | export enum SIZES {
12 | small = 'small',
13 | medium = 'medium',
14 | large = 'large'
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/ToggleSwitch/index.ts:
--------------------------------------------------------------------------------
1 | import {ToggleSwitch as ToggleSwitchComponent} from './ToggleSwitch';
2 | import {createHOC} from 'wix-ui-core/dist/src/createHOC';
3 |
4 | export const ToggleSwitch = createHOC(ToggleSwitchComponent);
5 |
--------------------------------------------------------------------------------
/src/components/Tooltip/Tooltip.driver.ts:
--------------------------------------------------------------------------------
1 | export {tooltipDriverFactory} from 'wix-ui-core/drivers/vanilla';
2 |
--------------------------------------------------------------------------------
/src/components/Tooltip/Tooltip.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { tooltipDriverFactory } from './Tooltip.driver';
3 | import { Tooltip } from './';
4 | import { createDriverFactory } from 'wix-ui-test-utils/driver-factory';
5 |
6 | describe('Tooltip', () => {
7 | const createDriver = createDriverFactory(tooltipDriverFactory);
8 |
9 | it('renders BO tooltip', () => {
10 | const tooltip = createDriver();
11 | expect(tooltip.exists()).toBeTruthy();
12 | });
13 |
14 | it('closing when hovered out', () => {
15 | const tooltip = createDriver();
16 | expect(tooltip.isContentElementExists()).toBeFalsy();
17 |
18 | tooltip.mouseEnter();
19 | expect(tooltip.isContentElementExists()).toBeTruthy();
20 |
21 | tooltip.mouseLeave();
22 | expect(tooltip.isContentElementExists()).toBeFalsy();
23 | });
24 |
25 | it('remains open when hovered out if relevant property is provided', () => {
26 | const tooltip = createDriver();
27 | expect(tooltip.isContentElementExists()).toBeFalsy();
28 |
29 | tooltip.mouseEnter();
30 | expect(tooltip.isContentElementExists()).toBeTruthy();
31 |
32 | tooltip.mouseLeave();
33 | expect(tooltip.isContentElementExists()).toBeTruthy();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/src/components/Tooltip/Tooltip.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "wix-ui-core/index.st.css";
3 | -st-named: Tooltip;
4 | }
5 |
6 | :import {
7 | -st-from: "../../colors.st.css";
8 | -st-named:
9 | D10,
10 | WHITE;
11 | }
12 |
13 | :import {
14 | -st-from: "../../typography.st.css";
15 | -st-named: fontRoman;
16 | }
17 |
18 | :import {
19 | -st-from: "../../shadows.st.css";
20 | -st-named: shadow30;
21 | }
22 |
23 | .root {
24 | -st-states: bounce, placement-right, placement-left, placement-top, placement-bottom;
25 | -st-extends: Tooltip;
26 | }
27 |
28 | .root::popoverContent {
29 | border: none;
30 |
31 | font-family: value(fontRoman);
32 | border-radius: 8px;
33 | padding: 12px 24px;
34 | box-sizing: border-box;
35 | font-size: 14px;
36 | line-height: 1.29;
37 | box-shadow: value(shadow30);
38 | word-wrap: break-word;
39 | -webkit-font-smoothing: antialiased;
40 |
41 | color: value(WHITE);
42 | background: value(D10);
43 | font-size: 14px;
44 | line-height: 18px;
45 | text-align: center;
46 | max-width: 230px;
47 | }
48 |
49 | .root:bounce::popover {
50 | animation-duration: 1.15s;
51 | animation-iteration-count: infinite;
52 | }
53 |
54 | .root:bounce:placement-right::popover {
55 | animation-name: right-bounce;
56 | }
57 |
58 | .root:bounce:placement-left::popover {
59 | animation-name: left-bounce;
60 | }
61 |
62 | .root:bounce:placement-top::popover {
63 | animation-name: top-bounce;
64 | }
65 |
66 | .root:bounce:placement-bottom::popover {
67 | animation-name: bottom-bounce;
68 | }
69 |
70 | @keyframes right-bounce {
71 | 0%, 100% { left: 5px; }
72 | 50% { left: -5px; }
73 | }
74 |
75 | @keyframes left-bounce {
76 | 0%, 100% { left: -5px; }
77 | 50% { left: 5px; }
78 | }
79 |
80 | @keyframes top-bounce {
81 | 0%, 100% { top: -5px; }
82 | 50% { top: 5px; }
83 | }
84 |
85 | @keyframes bottom-bounce {
86 | 0%, 100% { top: 5px; }
87 | 50% { top: -5px; }
88 | }
89 |
--------------------------------------------------------------------------------
/src/components/Tooltip/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Tooltip';
2 |
--------------------------------------------------------------------------------
/src/components/VBox/VBox.driver.ts:
--------------------------------------------------------------------------------
1 | export const vBoxDriverFactory = ({element}) => {
2 | return {
3 | /** check if element exists */
4 | exists: () => !!element,
5 | /** get the rendered content */
6 | getChildren: () => element.innerHTML
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/VBox/VBox.e2e.ts:
--------------------------------------------------------------------------------
1 | import * as eyes from 'eyes.it';
2 | import {browser} from 'protractor';
3 | import {getStoryUrl, waitForVisibilityOf} from 'wix-ui-test-utils/protractor';
4 | import {vBoxTestkitFactory} from '../../testkit/protractor';
5 |
6 | describe('VBox', () => {
7 | const storyUrl = getStoryUrl('Components', 'VBox');
8 |
9 | beforeEach(() => browser.get(storyUrl));
10 | eyes.it('should display correct content', () => {
11 | const dataHook = 'storybook-vbox';
12 | const driver = vBoxTestkitFactory({dataHook});
13 |
14 | return waitForVisibilityOf(driver.element(), 'Cannot find VBox');
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/components/VBox/VBox.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | export const vBoxDriverFactory = component => ({
2 | /** returns the component element */
3 | element: () => component
4 | });
5 |
--------------------------------------------------------------------------------
/src/components/VBox/VBox.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {mount} from 'enzyme';
3 | import {VBox} from './';
4 |
5 | describe('VBox', () => {
6 | let wrapper;
7 |
8 | afterEach(() => wrapper.detach());
9 |
10 | it('should render the passed children', () => {
11 | wrapper = mount(1
, {attachTo: document.createElement('div')});
12 | expect(wrapper.html()).toContain('1
');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/components/VBox/VBox.st.css:
--------------------------------------------------------------------------------
1 | .root {
2 | -st-states: horizontalAlignment(enum(left, center, right));
3 | display: flex;
4 | flex-direction: column;
5 | width: 100%;
6 | height: 100%;
7 | }
8 |
9 | .root:horizontalAlignment(left) {
10 | align-items: flex-start;
11 | }
12 |
13 | .root:horizontalAlignment(center) {
14 | align-items: center;
15 | }
16 |
17 | .root:horizontalAlignment(right) {
18 | align-items: flex-end;
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/VBox/VBox.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import style from './VBox.st.css';
3 | import {addSpacing} from './utils';
4 |
5 | export interface VBoxProps {
6 | children?: React.ReactNode;
7 | horizontalAlignment?: Alignment;
8 | spacing?: number;
9 | }
10 |
11 | export type Alignment = 'left' | 'center' | 'right';
12 |
13 | const defaultProps: VBoxProps = {
14 | children: null,
15 | horizontalAlignment: 'left',
16 | spacing: 0
17 | };
18 |
19 | /**
20 | * VBox
21 | */
22 | export const VBox: React.SFC = props => {
23 | const {children, horizontalAlignment, spacing} = props;
24 | return {addSpacing(children, spacing)}
;
25 | };
26 |
27 | VBox.displayName = 'VBox';
28 | VBox.defaultProps = defaultProps;
29 |
--------------------------------------------------------------------------------
/src/components/VBox/index.ts:
--------------------------------------------------------------------------------
1 | export {VBox, VBoxProps} from './VBox';
2 |
--------------------------------------------------------------------------------
/src/components/VBox/utils.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export function addSpacing (children, spacing: number) {
4 | if (!children || !spacing) {
5 | return children;
6 | }
7 |
8 | const spacedChildren = [];
9 |
10 | for (let i = 0; i < children.length - 1; i++) {
11 | spacedChildren.push(
12 | React.cloneElement(children[i], {style: {marginBottom: spacing}})
13 | );
14 | }
15 |
16 | spacedChildren.push(children[children.length - 1]);
17 |
18 | return spacedChildren;
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/core/CoreText/Text.driver.ts:
--------------------------------------------------------------------------------
1 | import {StylableDOMUtil} from '@stylable/dom-test-kit';
2 | import style from './Text.st.css';
3 | import {BaseDriver, DriverFactory} from 'wix-ui-test-utils/driver-factory';
4 |
5 | export interface TextDriver extends BaseDriver {
6 | hasEllipsis: () => boolean;
7 | hasTitleAttribute: () => boolean;
8 | getTitle: () => string;
9 | getTagName: () => string;
10 | getText: () => string;
11 | }
12 |
13 | export const textDriverFactory: DriverFactory = ({element}) => {
14 | const stylableDOMUtil = new StylableDOMUtil(style);
15 |
16 | return {
17 | /** check if element exists */
18 | exists: () => !!element,
19 | /** check if component has ellipsis */
20 | hasEllipsis: () => stylableDOMUtil.hasStyleState(element, 'ellipsis'),
21 | /** check if element has title attribute */
22 | hasTitleAttribute: () => element.getAttribute('title') !== null,
23 | /** check if element has title attribute */
24 | getTitle: () => (element as HTMLElement).title,
25 | /** get the rendered tag name */
26 | getTagName: () => element.tagName.toLowerCase(),
27 | /** get the rendered content */
28 | getText: () => element.innerHTML
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/src/components/core/CoreText/Text.protractor.driver.ts:
--------------------------------------------------------------------------------
1 | import {ElementFinder} from 'protractor';
2 |
3 | export interface TextDriver {
4 | element: () => ElementFinder;
5 | getText: () => Promise;
6 | }
7 |
8 | export const textDriverFactory = component => ({
9 | /** returns the component element */
10 | element: () => component,
11 | /** returns the component text */
12 | getText: async () => component.getText()
13 | });
14 |
--------------------------------------------------------------------------------
/src/components/core/CoreText/Text.st.css:
--------------------------------------------------------------------------------
1 | .root {
2 | -st-states: ellipsis;
3 | }
4 |
5 | /* ellipsis state */
6 | .root:ellipsis {
7 | display: block;
8 | text-overflow: ellipsis;
9 | overflow: hidden;
10 | white-space: nowrap;
11 | width: 100%;
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/core/CoreText/Text.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import style from './Text.st.css';
3 |
4 | export interface TextProps {
5 | children?: React.ReactNode;
6 | ellipsis?: boolean;
7 | forceHideTitle?: boolean;
8 | tagName?: string;
9 | className?: string;
10 | }
11 | /**
12 | * Text
13 | */
14 | export const Text: React.SFC = props => {
15 | const {children, ellipsis, tagName, forceHideTitle} = props;
16 | return React.createElement(
17 | tagName,
18 | {
19 | title: typeof children === 'string' && ellipsis && !forceHideTitle ? children : null,
20 | ...style('root', {ellipsis}, props)
21 | },
22 | children
23 | );
24 | };
25 |
26 | Text.displayName = 'Text';
27 | Text.defaultProps = {
28 | tagName: 'span'
29 | };
30 |
--------------------------------------------------------------------------------
/src/components/core/CoreText/TextStyle.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "./Text.st.css";
3 | -st-default: Text;
4 | }
5 |
6 | :vars {
7 | fontFamily: Arial;
8 | fontSize: 12px;
9 | lineHeight: normal;
10 | color: #000;
11 | textTransform: none;
12 | letterSpacing: normal;
13 | margin: 0;
14 | }
15 |
16 | .root {
17 | -st-extends: Text;
18 | font-family: value(fontFamily);
19 | font-size: value(fontSize);
20 | line-height: value(lineHeight);
21 | color: value(color);
22 | text-transform: value(textTransform);
23 | letter-spacing: value(letterSpacing);
24 | margin: value(margin);
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/core/CoreText/index.ts:
--------------------------------------------------------------------------------
1 | export {Text, TextProps} from './Text';
2 |
--------------------------------------------------------------------------------
/src/protractor.d.ts:
--------------------------------------------------------------------------------
1 | // This file is copy of 'wix-ui-core/node_modules/protractor/built/index.d.ts'
2 | // with fixes of protractor issue https://github.com/angular/protractor/issues/5348:
3 | // error TS2440: Import declaration conflicts with local declaration of 'PluginConfig'.
4 | // error TS2440: Import declaration conflicts with local declaration of 'ProtractorPlugin'.
5 |
6 | import { ElementHelper, ProtractorBrowser } from 'protractor/built/browser';
7 | import { ElementArrayFinder, ElementFinder } from 'protractor/built/element';
8 | import { ProtractorExpectedConditions } from 'protractor/built/expectedConditions';
9 | import { ProtractorBy } from 'protractor/built/locators';
10 | import { Ptor } from 'protractor/built/ptor';
11 | export { PluginConfig, ProtractorPlugin } from 'protractor/built/plugins';
12 | export {
13 | ActionSequence,
14 | Browser,
15 | Builder,
16 | Button,
17 | Capabilities,
18 | Capability,
19 | error,
20 | EventEmitter,
21 | FileDetector,
22 | Key,
23 | logging,
24 | promise,
25 | Session,
26 | until,
27 | WebDriver,
28 | WebElement,
29 | WebElementPromise,
30 | } from 'selenium-webdriver';
31 | export { ElementHelper, ProtractorBrowser } from 'protractor/built/browser';
32 | export { Config } from 'protractor/built/config';
33 | export { ElementArrayFinder, ElementFinder } from 'protractor/built/element';
34 | export { ProtractorExpectedConditions } from 'protractor/built/expectedConditions';
35 | export { Locator, ProtractorBy } from 'protractor/built/locators';
36 | export { Ptor } from 'protractor/built/ptor';
37 | export { Runner } from 'protractor/built/runner';
38 | export declare let utils: {
39 | firefox: any;
40 | http: any;
41 | remote: any;
42 | };
43 | export declare let Command: any;
44 | export declare let CommandName: any;
45 | export declare let protractor: Ptor;
46 | export declare let browser: ProtractorBrowser;
47 | export declare let $: (search: string) => ElementFinder;
48 | export declare let $$: (search: string) => ElementArrayFinder;
49 | export declare let element: ElementHelper;
50 | export declare let By: ProtractorBy;
51 | export declare let by: ProtractorBy;
52 | export declare let ExpectedConditions: ProtractorExpectedConditions;
53 |
--------------------------------------------------------------------------------
/src/shadows.st.css:
--------------------------------------------------------------------------------
1 | :vars {
2 | s1: rgba(22, 45, 61, 0.12);
3 | s2: rgba(22, 45, 61, 0.48);
4 | s3: rgba(22, 45, 61, 0.06);
5 | s4: rgba(22, 45, 61, 0.18);
6 | }
7 |
8 | :vars {
9 | shadow10: 0 2px 1px 0 value(s2), 0 0 3px 0 value(s1);
10 | shadow20: 0 2px 4px 0 value(s1), 0 0 6px 0 value(s1);
11 | shadow30: 0 6px 6px 0 value(s3), 0 0 18px 0 value(s1);
12 | shadow40: 0 8px 8px 0 value(s1), 0 3px 24px 0 value(s4);
13 | }
14 |
--------------------------------------------------------------------------------
/src/types/common.ts:
--------------------------------------------------------------------------------
1 | // coppied from type zoo: https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-377567046
2 | export type Omit = Pick>;
3 |
--------------------------------------------------------------------------------
/src/typography.st.css:
--------------------------------------------------------------------------------
1 | :vars {
2 | fontsFallback: '"Helvetica Neue", "Helvetica", "Arial", "メイリオ", "meiryo", "ヒラギノ角ゴ pro w3", "hiragino kaku gothic pro", "sans-serif"'
3 | }
4 |
5 | :vars {
6 | fontUltraThin: '"HelveticaNeueW01-UltLt", "HelveticaNeueW02-UltLt", "HelveticaNeueW10-25UltL", value(fontsFallback)';
7 | fontThin: '"HelveticaNeueW01-Thin", "HelveticaNeueW02-Thin", "HelveticaNeueW10-35Thin", value(fontsFallback)';
8 | fontLight: '"HelveticaNeueW01-45Ligh", "HelveticaNeueW02-45Ligh", "HelveticaNeueW10-45Ligh", value(fontsFallback)';
9 | fontRoman: '"HelveticaNeueW01-55Roma", "HelveticaNeueW02-55Roma", "HelveticaNeueW10-55Roma", value(fontsFallback)';
10 | fontMedium: '"HelveticaNeueW01-65Medi", "HelveticaNeueW02-65Medi", "HelveticaNeueW10-65Medi", value(fontsFallback)';
11 | fontBold: '"HelveticaNeueW01-75Bold", "HelveticaNeueW02-75Bold", "HelveticaNeueW10-75Bold", value(fontsFallback)';
12 | }
13 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export const hexToRgba = (hex, opacity) => {
2 | const r = parseInt(hex.substring(1, 3), 16);
3 | const g = parseInt(hex.substring(3, 5), 16);
4 | const b = parseInt(hex.substring(5, 7), 16);
5 | return `rgba(${r}, ${g}, ${b}, ${opacity})`;
6 | };
7 |
8 | export function enumValues(e: object) {
9 | return Object.keys(e).map(k => e[k as any]);
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/src/utils/utils.spec.ts:
--------------------------------------------------------------------------------
1 | import {hexToRgba, enumValues} from './';
2 |
3 | describe('hexToRgba function', () => {
4 | it('should transform hex to Rgba', () => {
5 | const opacity = 0;
6 | expect(hexToRgba('#4af441', opacity)).toBe(`rgba(74, 244, 65, ${opacity})`);
7 | });
8 | });
9 |
10 | describe('enumValues function', () => {
11 |
12 | it('should list enum values', () => {
13 | enum Foo {
14 | AAA= 'aaa',
15 | BBB= 'bbb'
16 | }
17 | expect(enumValues(Foo)).toEqual(['aaa','bbb']);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/stories/AddressInput.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { AddressInput } from '../src/components/AddressInput';
3 | import { Option } from 'wix-ui-core/dist/src/components/dropdown-option';
4 | import { GoogleMapsClientStub } from 'wix-ui-core/dist/src/components/address-input/GoogleMapsClientStub';
5 | import * as helper from 'wix-ui-core/dist/src/components/address-input/AddressInputTestHelper';
6 |
7 | GoogleMapsClientStub.setAddresses([helper.ADDRESS_1, helper.ADDRESS_2]);
8 | GoogleMapsClientStub.setGeocode(helper.GEOCODE_1);
9 |
10 | export default {
11 | category: 'Components',
12 | storyName: 'AddressInput',
13 | component: AddressInput,
14 | componentPath: '../src/components/AddressInput/AddressInput.tsx',
15 |
16 | componentProps: {
17 | 'data-hook': 'storybook-address-input',
18 | fixedFooter: 'Fixed Footer',
19 | fixedHeader: 'Fixed Header',
20 | Client: GoogleMapsClientStub
21 | },
22 |
23 | exampleProps: {
24 | onSelect: (option: Option) => option.value,
25 | onManualInput: (value: string) => `Manual input: ${value}`,
26 | onBlur: () => 'Triggered onBlur',
27 | onFocus: () => 'Triggered onFocus',
28 | onChange: evt => evt.target.value,
29 | size: ['small', 'medium', 'large']
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/stories/Autocomplete.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Autocomplete } from '../src/components/Autocomplete';
3 | import { generateDropdownOptions } from './helpers';
4 | import { Option, DividerArgs } from 'wix-ui-core/dist/src/components/dropdown-option';
5 |
6 | const options = generateDropdownOptions((args: Partial = {}) =>
7 | Autocomplete.createDivider(args.value)
8 | );
9 |
10 | const exampleOptions = [
11 | { value: options, label: '20 example options' },
12 | { value: options.slice(0, 1), label: '1 example option' },
13 | { value: options.slice(0, 5), label: '5 example options' }
14 | ];
15 |
16 | export default {
17 | category: 'Components',
18 | storyName: 'Autocomplete',
19 | component: Autocomplete,
20 | componentPath: '../src/components/Autocomplete/Autocomplete.tsx',
21 |
22 | componentProps: {
23 | 'data-hook': 'storybook-autocomplete',
24 | options: exampleOptions[2].value,
25 | fixedFooter: 'Fixed Footer',
26 | fixedHeader: 'Fixed Header'
27 | },
28 |
29 | exampleProps: {
30 | onSelect: (option: Option) => option.value,
31 | onManualInput: (value: string) => `Manual input: ${value}`,
32 | onBlur: () => 'Triggered onBlur',
33 | onFocus: () => 'Triggered onFocus',
34 | onChange: evt => evt.target.value,
35 | size: ['small', 'medium', 'large'],
36 |
37 | options: exampleOptions,
38 |
39 | initialSelectedId: [
40 | { value: [1], label: '[1]' },
41 | { value: [1, 2, 3], label: '[1, 2, 3]' }
42 | ]
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/stories/Badge/ExampleBadgeOnClick.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {Badge} from '../../src/components/Badge';
3 |
4 | export default () => (
5 | alert('Clicked!')}>
6 | I'm a badge!
7 |
8 | );
9 |
--------------------------------------------------------------------------------
/stories/Badge/ExampleBadges.scss:
--------------------------------------------------------------------------------
1 | .option {
2 | padding: 5px;
3 | }
4 |
5 | .wrapper {
6 | display: flex;
7 | align-items: center;
8 | padding: 5px;
9 | }
10 |
--------------------------------------------------------------------------------
/stories/Badge/ExampleBadges.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as styles from './ExampleBadges.scss';
3 |
4 | //import {Badge} from 'wix-ui-backoffice/Badge';
5 | import {Badge} from '../../src/components/Badge';
6 |
7 | //import {SIZE, SKIN, TYPE} from 'wix-ui-backoffice/Badge';
8 | import {SIZE, SKIN, TYPE} from '../../src/components/Badge';
9 |
10 | const skins = Object.keys(SKIN);
11 | const sizes = Object.keys(SIZE);
12 | const sizesString = sizes.join(', ');
13 | const types = Object.keys(TYPE);
14 | const typesString = types.join(', ');
15 |
16 | export default () => (
17 |
18 | {skins.map(skin => (
19 |
20 | skin: {skin} | sizes: {sizesString} | types: {typesString} | upppercase: true, false
21 |
22 | {renderSizes({skin})}
23 | {renderBadge({uppercase: false, skin})}
24 |
25 |
26 | )
27 | )}
28 |
);
29 |
30 | const renderSizes = props => (sizes.map(size => renderTypes({size, ...props})));
31 | const renderTypes = props => (types.map(type => renderBadge({type, ...props})));
32 |
33 | const renderBadge = props => (
34 |
35 | Some Badge
36 | );
37 |
38 |
39 |
--------------------------------------------------------------------------------
/stories/Badge/index.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import CodeExample from 'wix-storybook-utils/CodeExample';
3 |
4 | import * as ExampleBadgeOnClickRaw from '!raw-loader!./ExampleBadgeOnClick';
5 | import ExampleBadgeOnClick from './ExampleBadgeOnClick';
6 |
7 | import * as ExampleBadgesRaw from '!raw-loader!./ExampleBadges';
8 | import ExampleBadges from './ExampleBadges';
9 |
10 | import {SIZE, SKIN, TYPE} from '../../src/components/Badge/constants';
11 |
12 | import Facebook from 'wix-ui-icons-common/Facebook';
13 | import ChevronDown from 'wix-ui-icons-common/ChevronDown';
14 | import {Badge} from '../../src/components/Badge';
15 |
16 | const icons = [
17 | ,
18 |
19 | ];
20 |
21 | export default {
22 | category: 'Components',
23 | storyName: 'Badge',
24 | component: Badge,
25 | componentPath: '../../src/components/Badge/Badge.tsx',
26 |
27 | componentProps: {
28 | children: 'I\'m a badge!',
29 | skin: 'general',
30 | type: 'solid',
31 | size: 'medium',
32 | uppercase: true,
33 | dataHook: 'storybook-badge'
34 | },
35 |
36 | exampleProps: {
37 | skin: Object.keys(SKIN),
38 | type: Object.keys(TYPE),
39 | size: Object.keys(SIZE),
40 | prefixIcon: icons,
41 | suffixIcon: icons
42 | },
43 |
44 | examples: (
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | )
55 | };
56 |
--------------------------------------------------------------------------------
/stories/Button/index.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Button, ButtonProps, ButtonSkin as Skin, ButtonPriority as Priority, ButtonSize as Size } from '../../src/components/Button';
3 | import { storySettings } from './storySettings';
4 | import {enumValues} from '../../src/utils';
5 |
6 | function PButton(props: ButtonProps) {
7 | return (
8 |
9 |
12 |
13 | );
14 | }
15 |
16 | export default {
17 | category: storySettings.kind,
18 | storyName: storySettings.story,
19 | component: Button,
20 | componentPath: '../../src/components/Button/Button.tsx',
21 |
22 | componentProps: setState => ({
23 | 'data-hook': storySettings.dataHook,
24 | children: ['Click me!'],
25 | }),
26 |
27 | exampleProps: {
28 | skin: enumValues(Skin),
29 | priority: enumValues(Priority),
30 | size: enumValues(Size)
31 | },
32 |
33 | examples: (
34 |
35 |
Examples
36 |
Primary
37 |
38 |
39 |
40 |
41 |
Secondary
42 |
43 |
44 |
45 |
46 |
47 | )
48 | };
49 |
--------------------------------------------------------------------------------
/stories/Button/storySettings.ts:
--------------------------------------------------------------------------------
1 | import { StorySettings } from '../storyTypes';
2 |
3 | export const storySettings: StorySettings = {
4 | kind: 'Components',
5 | story: 'Button',
6 | dataHook: 'storybook-button'
7 | }
--------------------------------------------------------------------------------
/stories/Checkbox.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import Star from 'wix-ui-icons-common/Star';
4 | import StarFilled from 'wix-ui-icons-common/StarFilled';
5 | import Check from 'wix-ui-icons-common/Check';
6 |
7 | import {Checkbox} from '../src/components/Checkbox';
8 |
9 | const iconExamples = [
10 | ,
11 | ,
12 |
13 | ];
14 |
15 | export default {
16 | category: 'Components',
17 | storyName: 'Checkbox',
18 | component: Checkbox,
19 | componentPath: '../src/components/Checkbox/Checkbox.tsx',
20 |
21 | componentProps: setState => ({
22 | 'data-hook': 'storybook-checkbox',
23 | children: 'Hello World!',
24 | onChange: evt => setState({checked: evt.checked}),
25 | }),
26 |
27 | exampleProps: {
28 | onBlur: () => 'Triggered onBlur',
29 | onFocus: () => 'Triggered onFocus',
30 | onChange: evt => evt.checked ? 'Checked' : 'Unchecked',
31 | checkedIcon: iconExamples,
32 | uncheckedIcon: iconExamples,
33 | indeterminateIcon: iconExamples,
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/stories/CircularProgressBar/CircularProgressBar.story.tsx:
--------------------------------------------------------------------------------
1 | import { CircularProgressBar } from '../../src/components/CircularProgressBar';
2 | import {Size} from '../../src/components/CircularProgressBar/constants';
3 | import {enumValues} from '../../src/utils';
4 |
5 | export default {
6 | category: 'Components',
7 | name: 'CircularProgressBar',
8 | storyName: 'CircularProgressBar',
9 | component: CircularProgressBar,
10 |
11 | componentProps: {
12 | errorMessage: 'some error message',
13 | value: 20,
14 | size: 'large',
15 | 'data-hook': 'circular-progress-bar-story',
16 | light: false,
17 | error: false,
18 | errorLabel: '',
19 | showProgressIndication: false
20 | },
21 |
22 | exampleProps: {
23 | size: enumValues(Size)
24 | }
25 | }
--------------------------------------------------------------------------------
/stories/CircularProgressBar/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './CircularProgressBar.story';
2 |
--------------------------------------------------------------------------------
/stories/CloseButton/index.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import { CloseButton } from '../../src/components/CloseButton';
4 | import { enumValues } from '../../src/utils';
5 | import { Skin, Size } from '../../src/components/CloseButton/constants';
6 | import { storySettings } from './storySettings';
7 |
8 | export default {
9 | category: storySettings.kind,
10 | storyName: storySettings.story,
11 | component: CloseButton,
12 | componentPath: '../../src/components/CloseButton/CloseButton.tsx',
13 | componentProps: {
14 | 'data-hook': storySettings.dataHook
15 | },
16 | exampleProps: {
17 | size: enumValues(Size)
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/stories/CloseButton/storySettings.ts:
--------------------------------------------------------------------------------
1 | import { StorySettings } from '../storyTypes';
2 |
3 | export const storySettings: StorySettings = {
4 | kind: 'Internal',
5 | story: 'CloseButton',
6 | dataHook: 'storybook-close-button'
7 | }
--------------------------------------------------------------------------------
/stories/FloatingHelper/ControlledExample.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { FloatingHelper } from '../../src/components/FloatingHelper';
3 |
4 | export class ControlledExample extends React.Component {
5 | state= {open: true};
6 |
7 | render() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
I am a FloatingHelper target}
17 | content={
18 |
22 | }
23 | placement="right"
24 | />
25 |
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/stories/FloatingHelper/FullExample.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { FloatingHelper } from '../../src/components/FloatingHelper';
3 | import Image from 'wix-ui-icons-common/Image';
4 |
5 | export class FullExample extends React.Component {
6 | render() {
7 | return (
8 | I am a FloatingHelper target}
10 | content={
11 | null}
16 | image={}
17 | />
18 | }
19 | placement="right"
20 | />
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/stories/FloatingHelper/ProgrammaticExample.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | // import { FloatingHelper } from 'wix-ui-backoffice/FloatingHelper';
3 | import { FloatingHelper } from '../../src/components/FloatingHelper';
4 |
5 | export class ProgrammaticExample extends React.Component {
6 | helperRef: FloatingHelper;
7 |
8 | render() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
this.helperRef = ref}
17 | initiallyOpened={false}
18 | target={I am a FloatingHelper target}
19 | content={
20 |
24 | }
25 | placement="right"
26 | />
27 |
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/stories/FloatingHelper/SimpleExample.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { FloatingHelper } from '../../src/components/FloatingHelper';
3 |
4 | export class SimpleExample extends React.Component {
5 | render() {
6 | return (
7 | I am a FloatingHelper target}
9 | content={
10 |
14 | }
15 | placement="right"
16 | />
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/stories/FloatingHelper/SimpleExampleLight.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | FloatingHelper,
4 | Appearance
5 | } from '../../src/components/FloatingHelper';
6 | import Image from 'wix-ui-icons-common/Image';
7 | import { ActionButtonTheme } from '../../src/components/FloatingHelper/FloatingHelperContent';
8 |
9 | export class SimpleExampleLight extends React.Component {
10 | render() {
11 | return (
12 | I am a FloatingHelper target}
15 | content={
16 | null}
22 | image={
23 |
29 | }
30 | />
31 | }
32 | placement="right"
33 | appearance={Appearance.light}
34 | />
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/stories/FloatingHelper/StorySettings.ts:
--------------------------------------------------------------------------------
1 | import { StorySettings } from '../storyTypes';
2 |
3 | export const storySettings: StorySettings = {
4 | kind: 'Components',
5 | story: 'FloatingHelper',
6 | dataHook: 'story-floating-helper-right',
7 | };
8 |
--------------------------------------------------------------------------------
/stories/FloatingHelperContent/StorySettings.ts:
--------------------------------------------------------------------------------
1 | import { StorySettings } from '../storyTypes';
2 |
3 | export const storySettings: StorySettings = {
4 | kind: 'Internal',
5 | story: 'FloatingHelperContent',
6 | dataHook: 'story-floating-helper-content',
7 | exampleDataHooks: [
8 | 'example-body',
9 | 'example-title-body',
10 | 'example-title-body-action',
11 | 'example-body-action',
12 | 'example-title-body-action-premium',
13 | 'example-title-body-action-image',
14 | 'example-body-image',
15 | ]
16 | };
17 |
--------------------------------------------------------------------------------
/stories/FullTextView.story.tsx:
--------------------------------------------------------------------------------
1 | import {FullTextView} from '../src/components/FullTextView';
2 |
3 | export default {
4 | category: 'Components',
5 | storyName: 'FullTextView',
6 | component: FullTextView,
7 | componentPath: '../src/components/FullTextView/FullTextView.tsx',
8 |
9 | componentProps: setState => ({
10 | 'data-hook': 'storybook-fullTextView',
11 | children: 'Very long fancy and hardly fitting tab',
12 | maxWidth: '172px'
13 | }),
14 | };
15 |
--------------------------------------------------------------------------------
/stories/HBox/index.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import {HBox} from '../../src/components/HBox';
4 | import style from './style.st.css';
5 |
6 | const children = [1, 2, 3, 4, 5].map(i => hello
);
7 |
8 | export default {
9 | category: 'Components',
10 | storyName: 'HBox',
11 |
12 | component: HBox,
13 | componentPath: '../../src/components/HBox/HBox.tsx',
14 |
15 | componentProps: {
16 | ...style('root'),
17 | 'data-hook': 'storybook-hbox',
18 | children
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/stories/HBox/style.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "../../src/components/HBox/HBox.st.css";
3 | -st-default: HBox;
4 | }
5 |
6 | .root {
7 | -st-extends: HBox;
8 | border: solid green 2px;
9 | height: 100px;
10 | }
11 |
--------------------------------------------------------------------------------
/stories/Heading.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {Heading, Appearance} from '../src/components/Heading/Heading';
3 | import {enumValues} from '../src/utils';
4 |
5 | export default {
6 | category: 'Components',
7 | storyName: 'Heading',
8 | component: Heading,
9 | componentPath: '../src/components/Heading/Heading.tsx',
10 |
11 | componentProps: {
12 | 'data-hook': 'storybook-heading',
13 | children: 'Some text',
14 | light: false
15 | },
16 | exampleProps: {
17 | appearance: enumValues(Appearance)
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/stories/Input.story.tsx:
--------------------------------------------------------------------------------
1 | import {Input} from '../src/components/Input';
2 |
3 | export default {
4 | category: 'Components',
5 | storyName: 'Input',
6 | component: Input,
7 | componentPath: '../src/components/Input/Input.tsx',
8 |
9 | componentProps: setState => ({
10 | 'data-hook': 'storybook-input',
11 | value: 'Hello, World',
12 | placeholder: 'Greetings',
13 | error: false,
14 | onChange: event => setState({value: event.target.value})
15 | }),
16 |
17 | exampleProps: {
18 | prefix: ['Mrs.', 'Mr.', 'Prince'],
19 | suffix: ['$', '€'],
20 | onClick: () => 'Triggered onClick',
21 | onChange: () => 'Triggered onChange',
22 | onDoubleClick: () => 'Triggered onDoubleClick',
23 | onBlur: () => 'Triggered onBlur',
24 | onFocus: () => 'Triggered onFocus',
25 | onKeyDown: () => 'Triggered onKeyDown',
26 | onKeyUp: () => 'Triggered onKeyUp'
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/stories/Label.story.tsx:
--------------------------------------------------------------------------------
1 | import {Label} from '../src/components/Label';
2 | import * as LabelSource from '!raw-loader!../src/components/Label/Label.tsx';
3 |
4 | export default {
5 | category: 'Components',
6 | storyName: 'Label',
7 | component: Label,
8 | source: LabelSource,
9 | componentPath: '../src/components/Label/Label.tsx',
10 | componentProps: setState => ({
11 | 'data-hook': 'storybook-label',
12 | children: 'Some label',
13 | size: 'medium'
14 | }),
15 | exampleProps: {
16 | size: ['small', 'medium'],
17 | children: 'Some label'
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/stories/Label/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {storiesOf} from '@storybook/react';
3 | import {ToggleSwitch} from '../../src/components/ToggleSwitch';
4 | import {Autocomplete} from '../../src/components/Autocomplete';
5 | import {Heading} from '../../src/components/Heading';
6 | import {Input} from '../../src/components/Input';
7 | import {Label} from '../../src/components/Label';
8 | import {SIZES} from '../../src/components/Label/constants';
9 |
10 | const sizeOptions = Object.keys(SIZES).map(value => Autocomplete.createOption({id: value, value}));
11 |
12 | class ControlledLabelExample extends React.Component {
13 | constructor(props) {
14 | super(props);
15 | this.state = {
16 | size: SIZES.medium,
17 | children: 'Some label'
18 | };
19 | }
20 |
21 | render() {
22 | return(
23 |
24 |
25 |
26 |
32 |
33 |
Preview
34 |
35 |
41 |
42 |
43 |
44 |
45 | );
46 | }
47 | }
48 |
49 | storiesOf('Components', module)
50 | .add('Label', () => );
51 |
--------------------------------------------------------------------------------
/stories/LabelWithOptions.story.tsx:
--------------------------------------------------------------------------------
1 | import { LabelWithOptions } from '../src/components/LabelWithOptions';
2 | import { generateDropdownOptions } from './helpers';
3 | import { Option, DividerArgs } from 'wix-ui-core/dist/src/components/dropdown-option';
4 |
5 | const options = generateDropdownOptions((args: Partial = {}) =>
6 | LabelWithOptions.createDivider(args.value)
7 | );
8 |
9 | export default {
10 | category: 'Components',
11 | storyName: 'LabelWithOptions',
12 | component: LabelWithOptions,
13 | componentPath: '../src/components/LabelWithOptions/LabelWithOptions.tsx',
14 |
15 | componentProps: {
16 | 'data-hook': 'storybook-labelwithoptions',
17 | options,
18 | placeholder: 'With placeholder',
19 | fixedFooter: 'Fixed Footer',
20 | fixedHeader: 'Fixed Header'
21 | },
22 |
23 | exampleProps: {
24 | onSelect: (option: Option) => option.value,
25 | onDeselect: (option: Option) => option.value,
26 | size: ['small', 'medium', 'large'],
27 |
28 | options: [
29 | { value: options.slice(0, 1), label: '1 example option' },
30 | { value: options.slice(0, 5), label: '5 example options' },
31 | { value: options, label: '20 example options' }
32 | ]
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/stories/LinearProgressBar/LinearProgressBar.story.tsx:
--------------------------------------------------------------------------------
1 | import { LinearProgressBar } from '../../src/components/LinearProgressBar';
2 |
3 | export default {
4 | category: 'Components',
5 | name: 'LinearProgressBar',
6 | storyName: 'LinearProgressBar',
7 | component: LinearProgressBar,
8 |
9 | componentProps: {
10 | errorMessage: 'some error message',
11 | value: 20,
12 | 'data-hook': 'linear-progress-bar-story',
13 | light: false,
14 | error: false,
15 | showProgressIndication: false
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/stories/LinearProgressBar/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './LinearProgressBar.story';
2 |
--------------------------------------------------------------------------------
/stories/StylableCounterBadge/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {storiesOf} from '@storybook/react';
3 | import {CounterBadge} from '../../src/components/StylableCounterBadge';
4 | import {SKIN} from '../../src/components/StylableCounterBadge/constants';
5 | import Facebook from 'wix-ui-icons-common/Facebook';
6 | import {Autocomplete} from '../../src/components/Autocomplete';
7 | import {Heading} from '../../src/components/Heading';
8 |
9 | const skinOptions = Object.keys(SKIN).map(value => Autocomplete.createOption({id: value, value}));
10 |
11 | const iconsOptions = ['1', '12', '777', 'Facebook'].map(value => Autocomplete.createOption({id: value, value}));
12 |
13 | class ControlledCounterdBadgeExample extends React.Component {
14 | constructor(props) {
15 | super(props);
16 | this.state = {
17 | skin: SKIN.general,
18 | children: '12'
19 | };
20 | }
21 |
22 | render() {
23 | return(
24 |
25 |
26 |
Props
27 |
children: this.setState({children: value})} initialSelectedId={this.state.children}/>
28 | skin: this.setState({skin: value})} initialSelectedId={this.state.skin}/>
29 |
30 |
31 | Preview
32 |
36 | {this.state.children === 'Facebook' ? : this.state.children}
37 |
38 |
39 |
40 | );
41 | }
42 | }
43 |
44 | storiesOf('Components', module)
45 | .add('StylableCounterBadge', () => );
46 |
--------------------------------------------------------------------------------
/stories/Text.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {Text} from '../src/components/Text';
3 | import {Heading} from '../src/components/Heading';
4 |
5 | export default {
6 | category: 'Components',
7 | storyName: 'Text',
8 | component: Text,
9 | componentPath: '../src/components/Text/Text.tsx',
10 | displayName: 'Text',
11 |
12 | componentProps: {
13 | dataHook: 'storybook-text',
14 | children: 'Some text'
15 | },
16 |
17 | examples: (
18 |
19 | Multiline Example:
20 | {'First line\nSecond line'}
21 |
22 | )
23 | };
24 |
--------------------------------------------------------------------------------
/stories/Thumbnail.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import Image from 'wix-ui-icons-common/Image';
4 |
5 | import {Thumbnail} from '../src/components/Thumbnail';
6 |
7 | const image = ;
8 |
9 | export default {
10 | category: 'Components',
11 | storyName: 'Thumbnail',
12 | component: Thumbnail,
13 | componentPath: '../src/components/Thumbnail/Thumbnail.tsx',
14 |
15 | componentProps: {
16 | 'data-hook': 'storybook-thumbnail',
17 | title: 'Thumnbail Title',
18 | description: 'Description about this thumbnail option goes here',
19 | image
20 | },
21 |
22 | exampleProps: {
23 | image: [
24 | { label: 'small image', value: },
25 | { label: 'normal image', value: image },
26 | { label: 'big image', value: }
27 | ]
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/stories/TimePicker.story.tsx:
--------------------------------------------------------------------------------
1 | import { TimePicker } from '../src/components/TimePicker/TimePicker';
2 | import { enumValues } from '../src/utils';
3 | import { Size } from '../src/components/TimePicker/constants';
4 | import { TimePickerUtils } from 'wix-ui-core/dist/src/components/time-picker';
5 |
6 | const { leftpad } = TimePickerUtils;
7 | const now = new Date();
8 | const formattedNow = `${leftpad(now.getHours())}:${leftpad(now.getMinutes())}`;
9 |
10 | export default {
11 | category: 'Components',
12 | name: 'TimePicker',
13 | storyName: 'TimePicker',
14 | component: TimePicker,
15 | componentPath: '../src/components/TimePicker/TimePicker.tsx',
16 |
17 | componentProps: setState => ({
18 | 'data-hook': 'storybook-timePicker',
19 | error: false,
20 | disableAmPm: false,
21 | onChange: value => setState({ value })
22 | }),
23 |
24 | exampleProps: {
25 | size: enumValues(Size),
26 | onChange: value => value,
27 | value: [
28 | {
29 | label: `current time, ${formattedNow}`,
30 | value: `${formattedNow}`
31 | },
32 | {
33 | label: 'noon',
34 | value: '12:00'
35 | },
36 | {
37 | label: 'time to sleep',
38 | value: '02:34'
39 | }
40 | ]
41 | }
42 | };
43 |
--------------------------------------------------------------------------------
/stories/Tooltip/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {storiesOf} from '@storybook/react';
3 | import {Tooltip} from '../../src/components/Tooltip';
4 |
5 | function createTooltip(direction, bounce) {
6 | return (
7 |
16 | I need a tooltip
17 |
18 | );
19 | }
20 |
21 | class FullTooltip extends React.Component<{direction: string, bounce?: boolean}> {
22 | render() {
23 | const {direction, bounce} = this.props;
24 | return {createTooltip(direction, bounce)}
;
25 | }
26 | }
27 |
28 | storiesOf('Components', module)
29 | .add('Tooltip', () => (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | ));
38 |
--------------------------------------------------------------------------------
/stories/VBox/index.story.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import {VBox} from '../../src/components/VBox';
4 | import style from './style.st.css';
5 |
6 | const children = [1, 2, 3, 4, 5].map(i => hello
);
7 |
8 | export default {
9 | category: 'Components',
10 | storyName: 'VBox',
11 |
12 | component: VBox,
13 | componentPath: '../../src/components/VBox/VBox.tsx',
14 |
15 | componentProps: {
16 | ...style('root'),
17 | 'data-hook': 'storybook-vbox',
18 | children
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/stories/VBox/style.st.css:
--------------------------------------------------------------------------------
1 | :import {
2 | -st-from: "../../src/components/VBox/VBox.st.css";
3 | -st-default: VBox;
4 | }
5 |
6 | .root {
7 | -st-extends: VBox;
8 | border: solid green 2px;
9 | width: 100px;
10 | }
11 |
--------------------------------------------------------------------------------
/stories/helpers.tsx:
--------------------------------------------------------------------------------
1 | import { OptionFactory } from 'wix-ui-core/dist/src/components/dropdown-option';
2 |
3 | export const generateDropdownOptions = (
4 | dividerFactory = OptionFactory.createDivider
5 | ) => {
6 | const optionsExample = Array.from(Array(20)).map((x, index) =>
7 | OptionFactory.create({ id: index, value: `value${index}` })
8 | );
9 |
10 | optionsExample[2] = OptionFactory.create({
11 | id: 2,
12 | isDisabled: true,
13 | value: 'Disabled item'
14 | });
15 | optionsExample[5] = dividerFactory();
16 | optionsExample[8].value = 'This is a very very very very very long option';
17 | optionsExample[12] = dividerFactory({ value: 'Divider' });
18 | optionsExample[13] = OptionFactory.create({
19 | id: 13,
20 | value: 'Custom Item',
21 | render: value => {value}
22 | });
23 |
24 | return optionsExample;
25 | };
26 |
--------------------------------------------------------------------------------
/stories/index.ts:
--------------------------------------------------------------------------------
1 | import './AddressInput.story';
2 | import './Autocomplete.story';
3 | import './Checkbox.story';
4 | import './Badge/index.story';
5 | import './Button/index.story';
6 | import './CloseButton/index.story';
7 | import './FloatingHelper/index.story';
8 | import './FloatingHelperContent/index.story';
9 | import './FullTextView.story';
10 | import './StylableCounterBadge';
11 | import './Heading.story';
12 | import './Label';
13 | import './LinearProgressBar';
14 | import './CircularProgressBar';
15 | import './Input.story.tsx';
16 | import './LabelWithOptions.story';
17 | import './ToggleSwitch';
18 | import './Tooltip';
19 | import './Thumbnail.story';
20 | import './HBox/index.story';
21 | import './VBox/index.story';
22 | import './Text.story';
23 | import './TimePicker.story';
24 |
--------------------------------------------------------------------------------
/stories/storyTypes.ts:
--------------------------------------------------------------------------------
1 | import { StoryUrlParams } from 'wix-ui-test-utils/dist/src/protractor/';
2 |
3 | export interface StorySettings extends StoryUrlParams {
4 | kind: 'Internal' | 'Components';
5 | dataHook: string;
6 | exampleDataHooks?: string[];
7 | }
8 |
--------------------------------------------------------------------------------
/test/enzyme-setup.js:
--------------------------------------------------------------------------------
1 | const Enzyme = require('enzyme');
2 | const Adapter = require('enzyme-adapter-react-16');
3 |
4 | Enzyme.configure({adapter: new Adapter()});
5 |
--------------------------------------------------------------------------------
/test/testkitUtils.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {mount, ReactWrapper} from 'enzyme';
3 | import { enzymeTestkitFactoryCreator } from 'wix-ui-test-utils/enzyme';
4 | import { BaseDriver, DriverFactory } from 'wix-ui-test-utils/driver-factory';
5 |
6 | /* TODO: Add this to wix-ui-test-utils or
7 | * change wix-ui-test-utils/enzyme's enzymeTestkitFactoryCreator to return the
8 | * wrapper and wrapperInstance as well.
9 | */
10 | export function createEnzymeDriverFactory, T extends BaseDriver>(driverFactory: DriverFactory) {
11 | function createEnzymeDriver(element: React.ReactElement) {
12 | const dataHook = 'arbitrary-hook';
13 | const enzymeTestkitFactory = enzymeTestkitFactoryCreator(driverFactory);
14 | const wrapper = mount(React.cloneElement(element, { 'data-hook': dataHook }));
15 | const driver = enzymeTestkitFactory({ wrapper, dataHook });
16 | return { wrapper, driver, wrapperInstance: wrapper.instance() as C };
17 | }
18 |
19 | return createEnzymeDriver;
20 | }
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "sourceMap": true,
4 | "module": "commonjs",
5 | "declaration": true,
6 | "strict": false,
7 | "moduleResolution": "node",
8 | "target": "es5",
9 | "jsx": "react",
10 | "lib": ["dom", "es2016", "esnext.asynciterable"],
11 | "baseUrl": "./",
12 | "paths": {
13 | "*": ["node_modules/@types/*", "*"],
14 | "protractor": ["src/protractor.d.ts"] // Fix protractor issue https://github.com/angular/protractor/issues/5348
15 | }
16 | },
17 | "include": [
18 | "./node_modules/wix-ui-core/dist/src/globals.d.ts",
19 | "./node_modules/wix-ui-core/dist/src/types.d.ts",
20 | "./src/**/*.ts",
21 | "./src/**/*.tsx"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "tslint-config-wix",
4 | "tslint-react",
5 | "tslint-config-prettier"
6 | ],
7 | "rules": {
8 | "comma-dangle": ["error", "never"],
9 | "jsx-no-multiline-js": false,
10 | "jsx-no-lambda": false,
11 | "jsx-boolean-value": [true, "never"],
12 | "jsx-alignment": true,
13 | "jsx-wrap-multiline": true,
14 | "space-in-brackets": ["error", "always"],
15 | "arrow-parens": [true, "ban-single-arg-parens"],
16 | "array-bracket-spacing": [true, "never"],
17 | "quotemark": [true, "single", "jsx-double"]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/wallaby.js:
--------------------------------------------------------------------------------
1 | module.exports = require('yoshi/config/wallaby-jest');
2 |
--------------------------------------------------------------------------------