Compare commits

..
Author SHA1 Message Date
github-actions[bot] a170ca8998 Lerna versionbump [ci skip]
- @navikt/ds-css@0.9.2
 - @navikt/ds-react@0.10.3
 - @navikt/ds-react-internal@0.5.1
2021-10-15 13:24:12 +00:00
347427c6e6 [fix] Table component (#1286)
* simplify tsconfig of @navikt/ds-react-internal

* placeholder-componenter for tabell

* split into headercell and normal cell

* varianter av tabell

* støtter både zebra og vertikale striper

* midlertidig fix for exluding av stories

* litt endringer i api og props etter diskusjon med andreas

* fjerner styling-props

* rydder

* rydder

* flytter til core

* rydder

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2021-10-15 15:11:29 +02:00
Ken 35aab3b672 [FIX] Workflow fungerer nå, la tilbake build-steps 2021-10-15 12:28:26 +02:00
Ken 5f4c0a7a2d [FIX] publish med no-verify-access 2021-10-15 12:20:17 +02:00
Ken fd120b65e0 [FIX] tester alternativt oppsett av node for npm publish2 2021-10-15 12:10:44 +02:00
Ken 3ae1be923e [FIX] tester alternativt oppsett av node for npm publish 2021-10-15 12:06:22 +02:00
Ken dab2c3f2c2 [FIX] temp fjernet test for å gjøre build raskere 2021-10-15 11:37:56 +02:00
Ken c0f1b8401e oppdatert workflow 2021-10-15 11:36:06 +02:00
Ken 8ba8936fdd [FIX] Oppdatert Readme 2021-10-14 15:09:09 +02:00
Andreas Nordahl 15c5845465 delete unused util scripts (#1284) 2021-10-12 20:16:37 +02:00
github-actions[bot] f6bc0c612f Lerna versionbump [ci skip]
- @navikt/ds-css-internal@0.5.0
 - @navikt/ds-react-internal@0.5.0
2021-10-12 12:51:44 +00:00
Andreas NordahlandIda Onshus b796e306d5 [feature] Dropdown menu with description list for heading hierarchy (#1283)
* header dl wip

* header dl wip

* legger til descriptionlist-komponenter i dropdown menu for internflateheader

* some cleanup

* use new dropdown api in header stories

* rename and restructure grouped lsit

* change dropdown menu api to contain toggle and context

* wip

* complete implementation of new dropdown api

* use dropdown directly in header

* unused imports

* remove uneccesary dropdownId

Co-authored-by: Ida Onshus <25682301+idaons@users.noreply.github.com>
2021-10-12 14:38:28 +02:00
IdaandAndreas Nordahl 0e9680dab9 oppdaterer readme for yarn install med mac m1 (#1282)
* oppdaterer readme for yarn install med macm1

* Update CONTRIBUTING.md

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>

* Update CONTRIBUTING.md

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>

* Update CONTRIBUTING.md

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2021-10-11 11:13:03 +02:00
Ken 6d2858c6e1 whoami 2021-10-11 10:52:05 +02:00
Ken 9294410ed8 forsøk på npm fix 2021-10-11 10:51:03 +02:00
github-actions[bot] e3653580e6 Lerna versionbump [ci skip]
- @navikt/ds-css-internal@0.4.0
 - @navikt/ds-react-internal@0.4.0
2021-10-08 07:50:38 +00:00
Andreas Nordahl c9ab2e1516 [feature] remove unused header button (#1281) 2021-10-08 09:35:51 +02:00
Andreas Nordahl bb1876df43 remove list component from dropdown to simplify API (#1280) 2021-10-08 09:21:27 +02:00
github-actions[bot] d98bff30f6 Lerna versionbump [ci skip]
- @navikt/ds-css-internal@0.3.1
 - @navikt/ds-react-internal@0.3.1
2021-10-07 14:45:58 +00:00
Andreas Nordahl 7f53011d91 [fix] Header uu (#1279)
* render user name and desc as div

* dont use heading for menu title

* unused import
2021-10-07 16:29:29 +02:00
github-actions[bot] 4a451fe84a Lerna versionbump [ci skip]
- @navikt/ds-css-internal@0.3.0
 - @navikt/ds-react-internal@0.3.0
2021-10-07 13:01:29 +00:00
Andreas Nordahl 01adced0e7 [feature] Internal header dropdown menus (#1276)
* dot notation

* refactor HeaderTitle

* WIP

* separate story

* header dropdown

* add generic dropdown and divider

* some cleanup

* initial draft complete

* unused import

* revert overridable component

* width hover and focus

* wrap items in list and add roles

* delete outdated mdx stories

* new Header.dropdown api

* some cleanup

* height

* some cleanup

* lots of styling fixes

* user button component

* rename classes

* spacing fix

* title

* dropdown max-height

* color cleanup

* fix typo
2021-10-07 14:45:43 +02:00
Ken e2bae872cf [FIX] registry fix 2 2021-10-05 19:25:21 +02:00
Ken aff8f00ade registry fix 2 2021-10-05 19:24:47 +02:00
Ken ad28279bd3 [FIX] Endret npm registry til https fra http (#1278) 2021-10-05 17:30:48 +02:00
52 changed files with 1011 additions and 719 deletions

No files matched your search

+6 -12
View File
@@ -55,15 +55,17 @@ jobs:
publish-npm:
needs: test-build
runs-on: ubuntu-latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTOMATION }}
if: github.event_name == 'push' && contains(github.event.head_commit.message, '[fix]') || contains(github.event.head_commit.message, '[feature]') || contains(github.event.head_commit.message, '[breaking]')
steps:
- uses: actions/checkout@v2
with:
fetch-depth: "0"
token: ${{secrets.GIT_REPO}}
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
registry-url: http://registry.npmjs.org
registry-url: https://registry.npmjs.org
node-version: 14
- name: Node-modules cache
uses: actions/cache@v2
@@ -93,17 +95,9 @@ jobs:
- name: Update changed packages with MAJOR
if: "contains(github.event.head_commit.message, '[breaking]')"
run: yarn lerna version major --include-merged-tags --yes
- name: Create a .npmrc file for NPM
run: |
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
npm whoami
env:
NPM_TOKEN: ${{secrets.NPM_AUTOMATION}}
- name: Publish to NPM registry
run: |
yarn lerna publish from-package --yes
rm .npmrc
run: yarn lerna publish --no-verify-access from-package --yes
- name: Create a .npmrc file for the github package repository
uses: FerLuisxd/create-npmrc@3
with:
+1
View File
@@ -19,6 +19,7 @@
@import "panel.css";
@import "link-panel.css";
@import "speech-bubble.css";
@import "table.css";
/* Navno spesific packages */
@import "page-header.css";
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "0.9.1",
"version": "0.9.2",
"private": false,
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
+28
View File
@@ -0,0 +1,28 @@
.navds-table {
border-collapse: collapse;
width: 100%;
display: table;
}
.navds-table__header {
display: table-header-group;
}
.navds-table__body {
display: table-row-group;
}
.navds-table__row {
display: table-row;
}
.navds-table__cell {
display: table-cell;
padding: var(--navds-spacing-4);
text-align: left;
border-bottom: var(--navds-border-default);
}
.navds-table--small .navds-table__cell {
padding: var(--navds-spacing-2);
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "0.10.2",
"version": "0.10.3",
"private": false,
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
+1
View File
@@ -15,6 +15,7 @@ export * from "./panel";
export * from "./popover";
export * from "./speech-bubble";
export * from "./tag";
export * from "./table";
export * from "./typography";
export * from "./util";
+15
View File
@@ -0,0 +1,15 @@
import React, { forwardRef } from "react";
import cl from "classnames";
interface BodyProps extends React.HTMLAttributes<HTMLTableSectionElement> {}
export interface BodyType
extends React.ForwardRefExoticComponent<
BodyProps & React.RefAttributes<HTMLTableSectionElement>
> {}
const Body: BodyType = forwardRef(({ className, ...rest }, ref) => (
<tbody {...rest} ref={ref} className={cl("navds-table__body", className)} />
));
export default Body;
+15
View File
@@ -0,0 +1,15 @@
import React, { forwardRef } from "react";
import cl from "classnames";
interface DataCellProps extends React.HTMLAttributes<HTMLTableCellElement> {}
export interface DataCellType
extends React.ForwardRefExoticComponent<
DataCellProps & React.RefAttributes<HTMLTableCellElement>
> {}
const DataCell: DataCellType = forwardRef(({ className, ...rest }, ref) => (
<td {...rest} ref={ref} className={cl("navds-table__cell", className)} />
));
export default DataCell;
+15
View File
@@ -0,0 +1,15 @@
import React, { forwardRef } from "react";
import cl from "classnames";
interface HeaderProps extends React.HTMLAttributes<HTMLTableSectionElement> {}
export interface HeaderType
extends React.ForwardRefExoticComponent<
HeaderProps & React.RefAttributes<HTMLTableSectionElement>
> {}
const Header: HeaderType = forwardRef(({ className, ...rest }, ref) => (
<thead {...rest} ref={ref} className={cl("navds-table__header", className)} />
));
export default Header;
@@ -0,0 +1,15 @@
import React, { forwardRef } from "react";
import cl from "classnames";
interface HeaderCellProps extends React.HTMLAttributes<HTMLTableCellElement> {}
export interface HeaderCellType
extends React.ForwardRefExoticComponent<
HeaderCellProps & React.RefAttributes<HTMLTableCellElement>
> {}
const HeaderCell: HeaderCellType = forwardRef(({ className, ...rest }, ref) => (
<th {...rest} ref={ref} className={cl("navds-table__cell", className)} />
));
export default HeaderCell;
+15
View File
@@ -0,0 +1,15 @@
import React, { forwardRef } from "react";
import cl from "classnames";
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {}
export interface RowType
extends React.ForwardRefExoticComponent<
RowProps & React.RefAttributes<HTMLTableRowElement>
> {}
const Row: RowType = forwardRef(({ className, ...rest }, ref) => (
<tr {...rest} ref={ref} className={cl("navds-table__row", className)} />
));
export default Row;
+42
View File
@@ -0,0 +1,42 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import Header, { HeaderType } from "./Header";
import Body, { BodyType } from "./Body";
import Row, { RowType } from "./Row";
import HeaderCell, { HeaderCellType } from "./HeaderCell";
import DataCell, { DataCellType } from "./DataCell";
export interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
/**
* Changes padding
* @default "medium"
*/
size?: "medium" | "small";
}
export interface TableType
extends React.ForwardRefExoticComponent<
TableProps & React.RefAttributes<HTMLTableElement>
> {
Header: HeaderType;
Body: BodyType;
Row: RowType;
DataCell: DataCellType;
HeaderCell: HeaderCellType;
}
const Table = forwardRef(({ className, size = "medium", ...rest }, ref) => (
<table
{...rest}
ref={ref}
className={cl("navds-table", `navds-table--${size}`, className)}
/>
)) as TableType;
Table.Header = Header;
Table.Body = Body;
Table.Row = Row;
Table.HeaderCell = HeaderCell;
Table.DataCell = DataCell;
export default Table;
+2
View File
@@ -0,0 +1,2 @@
export { default as Table } from "./Table";
export * from "./Table";
@@ -0,0 +1,139 @@
import React from "react";
import { Table } from "../index";
import { Alert, Link } from "@navikt/ds-react";
export default {
title: "ds-react/table",
component: Table,
};
export const All = () => {
return (
<>
<h1>Table</h1>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>ID</Table.HeaderCell>
<Table.HeaderCell>Fornavn</Table.HeaderCell>
<Table.HeaderCell>Etternavn</Table.HeaderCell>
<Table.HeaderCell>Rolle</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.HeaderCell>1</Table.HeaderCell>
<Table.DataCell>Jean-Luc</Table.DataCell>
<Table.DataCell>Picard</Table.DataCell>
<Table.DataCell>Kaptein</Table.DataCell>
</Table.Row>
<Table.Row>
<Table.HeaderCell>2</Table.HeaderCell>
<Table.DataCell>William</Table.DataCell>
<Table.DataCell>Riker</Table.DataCell>
<Table.DataCell>Kommandør</Table.DataCell>
</Table.Row>
<Table.Row>
<Table.HeaderCell>3</Table.HeaderCell>
<Table.DataCell>Geordi</Table.DataCell>
<Table.DataCell>La Forge</Table.DataCell>
<Table.DataCell>Sjefsingeniør</Table.DataCell>
</Table.Row>
</Table.Body>
</Table>
<h2>Small Table</h2>
<Table size="small">
<Table.Header>
<Table.Row>
<Table.HeaderCell>ID</Table.HeaderCell>
<Table.HeaderCell>Fornavn</Table.HeaderCell>
<Table.HeaderCell>Etternavn</Table.HeaderCell>
<Table.HeaderCell>Rolle</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.HeaderCell>1</Table.HeaderCell>
<Table.DataCell>Jean-Luc</Table.DataCell>
<Table.DataCell>Picard</Table.DataCell>
<Table.DataCell>Kaptein</Table.DataCell>
</Table.Row>
<Table.Row>
<Table.HeaderCell>2</Table.HeaderCell>
<Table.DataCell>William</Table.DataCell>
<Table.DataCell>Riker</Table.DataCell>
<Table.DataCell>Kommandør</Table.DataCell>
</Table.Row>
<Table.Row>
<Table.HeaderCell>3</Table.HeaderCell>
<Table.DataCell>Geordi</Table.DataCell>
<Table.DataCell>La Forge</Table.DataCell>
<Table.DataCell>Sjefsingeniør</Table.DataCell>
</Table.Row>
</Table.Body>
</Table>
<h2>Table with divs</h2>
<Alert variant="warning">
Obs! Hvis man skal bygge tabeller uten å bruke vanlig {"<tabell> "}
-markup er det svært viktig at man supplerer elementene med{" "}
<Link href="https://www.w3.org/TR/wai-aria-practices-1.1/examples/table/table.html">
riktige
</Link>{" "}
role-attributter og display-stiler for å bevare den semantiske verdien i
tabellene. Vi anbefaler fortsatt å ikke ta i bruk denne metoden hvis
mulig, da nettleseren ikke kan tolke tabellen like bra uten riktig
markup.
</Alert>
<div className="navds-table navds-table--zebra" role="table">
<div className="navds-table__header" role="rowgroup">
<div className="navds-table__row" role="row">
<div className="navds-table__cell" role="columnheader">
ID
</div>
<div className="navds-table__cell" role="columnheader">
Fornavn
</div>
<div className="navds-table__cell" role="columnheader">
Etternavn
</div>
</div>
</div>
<div className="navds-table__body" role="rowgroup">
<div className="navds-table__row" role="row">
<div className="navds-table__cell" role="cell">
Jean-Luc
</div>
<div className="navds-table__cell" role="cell">
Picard
</div>
<div className="navds-table__cell" role="cell">
Kaptein
</div>
</div>
<div className="navds-table__row" role="row">
<div className="navds-table__cell" role="cell">
William
</div>
<div className="navds-table__cell" role="cell">
Riker
</div>
<div className="navds-table__cell" role="cell">
Kommandør
</div>
</div>
<div className="navds-table__row" role="row">
<div className="navds-table__cell" role="cell">
Geordi
</div>
<div className="navds-table__cell" role="cell">
La Forge
</div>
<div className="navds-table__cell" role="cell">
Sjefsingeniør
</div>
</div>
</div>
</div>
</>
);
};
+5
View File
@@ -0,0 +1,5 @@
.navdsi-divider {
margin: var(--navds-spacing-3) 0;
border: none;
border-bottom: 1px solid var(--navds-color-gray-40);
}
+56
View File
@@ -0,0 +1,56 @@
.navdsi-dropdown__menu {
overflow: hidden;
padding: var(--navds-spacing-4) 0;
color: var(--navds-color-darkgray);
width: 27ch;
max-height: 616px;
overflow-y: auto;
}
.navdsi-dropdown__menu > :not(.navdsi-divider):not(.navdsi-dropdown__list) {
margin: 0 var(--navds-spacing-4) var(--navds-spacing-3);
}
.navdsi-dropdown__list {
margin: 0;
padding: 0;
list-style: none;
}
.navdsi-dropdown__list-item {
margin: 0;
}
.navdsi-dropdown__list-heading {
margin: 0 var(--navds-spacing-4) var(--navds-spacing-4);
}
.navdsi-dropdown__item {
border: none;
margin: 0;
overflow: visible;
background: transparent;
color: var(--navds-color-text-link);
font: inherit;
text-decoration: none;
text-align: left;
cursor: pointer;
width: 100%;
display: flex;
align-items: center;
gap: var(--navds-spacing-2);
padding: var(--navds-spacing-1) var(--navds-spacing-4);
}
.navdsi-dropdown__item:hover {
background-color: var(--navds-color-blue-10);
}
.navdsi-dropdown__item:active {
background-color: var(--navds-color-blue-20);
}
.navdsi-dropdown__item:focus {
outline: none;
box-shadow: inset 0 0 0 2px var(--navds-color-blue-80);
}
+52 -34
View File
@@ -2,63 +2,81 @@
--navdsi-header-color-background: var(--navds-color-darkgray);
--navdsi-header-color-border: var(--navds-color-gray-40);
--navdsi-header-color-text: var(--navds-color-text-inverse);
--navdsi-header-focus: inset 0 0 0 2px var(--navds-color-blue-10);
}
/**************************
* .navdsi-header *
**************************/
.navdsi-header {
display: flex;
align-items: center;
align-self: stretch;
background: var(--navdsi-header-color-background);
color: var(--navdsi-header-color-text);
max-width: 100vw;
min-height: 50px;
min-height: var(--navds-spacing-12);
}
.navdsi-header__column {
display: flex;
align-items: center;
}
/**************************
* .navdsi-header__title *
**************************/
.navdsi-header__title {
padding: 0 var(--navds-spacing-6);
border: none;
overflow: visible;
background: transparent;
font: inherit;
line-height: normal;
text-align: left;
padding: 0 var(--navds-spacing-5) 0 var(--navds-spacing-6);
border-right: 1px solid var(--navdsi-header-color-border);
display: flex;
align-self: stretch;
align-items: center;
text-decoration: none;
margin: 0;
color: var(--navdsi-header-color-text);
font-size: var(--navds-font-size-l);
font-weight: var(--navds-font-weight-bold);
line-height: var(--navds-font-line-height-l);
}
.navdsi-header__title:focus {
box-shadow: inset var(--navds-shadow-focus-on-dark);
outline: none;
button.navdsi-header__title {
cursor: pointer;
}
/**************************
* .navdsi-header__user *
**************************/
.navdsi-header__user {
color: var(--navdsi-header-color-text);
padding: 0 var(--navds-spacing-6);
margin-left: auto;
padding: 0 var(--navds-spacing-5);
border-left: 1px solid var(--navdsi-header-color-border);
display: flex;
align-self: stretch;
align-items: center;
}
.navdsi-header__name.navds-body-short {
margin-right: var(--navds-spacing-4);
.navdsi-header__button {
border: none;
margin: 0;
padding: 0 var(--navds-spacing-3);
overflow: visible;
background: transparent;
font: inherit;
line-height: normal;
cursor: pointer;
text-align: left;
display: flex;
align-items: center;
justify-self: center;
gap: var(--navds-spacing-2);
border-left: 1px solid var(--navdsi-header-color-border);
color: var(--navdsi-header-color-text);
}
a.navdsi-header__title:hover,
button.navdsi-header__title:hover,
.navdsi-header__button:hover {
background-color: var(--navds-color-gray-80);
}
.navdsi-header__title:focus,
.navdsi-header__button:focus {
box-shadow: var(--navdsi-header-focus);
outline: none;
}
a.navdsi-header__title:active,
button.navdsi-header__title:active,
.navdsi-header__button:active {
background-color: var(--navds-color-gray-60);
}
.navdsi-header__user-button {
padding-left: var(--navds-spacing-5);
gap: var(--navds-spacing-4);
}
+2
View File
@@ -1 +1,3 @@
@import "divider.css";
@import "dropdown.css";
@import "header.css";
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "0.2.0",
"version": "0.5.0",
"private": false,
"description": "Css for NAV internal Designsystem components",
"author": "NAV Designsystem team",
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "0.2.1",
"version": "0.5.1",
"private": false,
"description": "NAV internal designsystem react components",
"author": "NAV Designsystem team",
@@ -33,7 +33,8 @@
"watch": "tsc --watch -p tsconfig-esm.json"
},
"dependencies": {
"@navikt/ds-react": "^0.10.2",
"@navikt/ds-icons": "^0.5.4",
"@navikt/ds-react": "^0.10.3",
"classnames": "^2.3.1"
},
"devDependencies": {
@@ -0,0 +1,12 @@
import React, { forwardRef } from "react";
import cl from "classnames";
export interface DividerProps extends React.HTMLAttributes<HTMLHRElement> {}
const Divider = forwardRef<HTMLHRElement, DividerProps>(
({ className, ...rest }, ref) => (
<hr {...rest} ref={ref} className={cl("navdsi-divider", className)} />
)
);
export default Divider;
@@ -0,0 +1,2 @@
export { default as Divider } from "./Divider";
export * from "./Divider";
@@ -0,0 +1,40 @@
import React, { createContext, useState } from "react";
import Toggle, { ToggleType } from "./Toggle";
import Menu, { MenuType } from "./Menu";
export interface DropdownType extends React.FC {
Toggle: ToggleType;
Menu: MenuType;
}
export interface DropdownContextType {
readonly isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
readonly anchorEl: Element | null;
setAnchorEl: React.Dispatch<React.SetStateAction<Element | null>>;
}
export const DropdownContext = createContext<DropdownContextType | null>(null);
const Dropdown = (({ children }) => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const [anchorEl, setAnchorEl] = useState<Element | null>(null);
return (
<DropdownContext.Provider
value={{
isOpen,
setIsOpen,
anchorEl,
setAnchorEl,
}}
>
{children}
</DropdownContext.Provider>
);
}) as DropdownType;
Dropdown.Toggle = Toggle;
Dropdown.Menu = Menu;
export default Dropdown;
@@ -0,0 +1,28 @@
import React, { forwardRef } from "react";
import cl from "classnames";
export interface HeadingProps extends React.HTMLAttributes<HTMLDetailsElement> {
/**
* Heading
*/
children: React.ReactNode;
}
export type HeadingType = React.ForwardRefExoticComponent<
HeadingProps & React.RefAttributes<HTMLElement>
>;
const Heading: HeadingType = forwardRef(({ className, ...rest }, ref) => (
<dt
{...rest}
ref={ref}
className={cl(
"navdsi-dropdown__list-heading",
"navds-heading",
"navds-heading--xsmall",
className
)}
/>
));
export default Heading;
@@ -0,0 +1,31 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { OverridableComponent } from "@navikt/ds-react";
export interface ItemProps extends React.ButtonHTMLAttributes<HTMLElement> {
/**
* Menu item content
*/
children: React.ReactNode;
}
export type ItemType = OverridableComponent<ItemProps, HTMLButtonElement>;
const Item: ItemType = forwardRef(
({ as: Component = "button", className, ...rest }, ref) => (
<dd className="navdsi-dropdown__list-item">
<Component
{...rest}
ref={ref}
className={cl(
"navdsi-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className
)}
/>
</dd>
)
);
export default Item;
@@ -0,0 +1,31 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import Heading, { HeadingType } from "./Heading";
import Item, { ItemType } from "./Item";
export interface GroupedListProps
extends React.HTMLAttributes<HTMLDListElement> {
/**
* Menu list content
*/
children: React.ReactNode;
}
export interface GroupedListType
extends React.ForwardRefExoticComponent<
GroupedListProps & React.RefAttributes<HTMLDListElement>
> {
Heading: HeadingType;
Item: ItemType;
}
const DescriptionList = forwardRef(({ className, children, ...rest }, ref) => (
<dl {...rest} ref={ref} className={cl("navdsi-dropdown__list", className)}>
{children}
</dl>
)) as GroupedListType;
DescriptionList.Heading = Heading;
DescriptionList.Item = Item;
export default DescriptionList;
@@ -0,0 +1,32 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { OverridableComponent } from "@navikt/ds-react";
export interface ItemProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* Menu item content
*/
children: React.ReactNode;
}
export type ItemType = OverridableComponent<ItemProps, HTMLButtonElement>;
const Item: ItemType = forwardRef(
({ as: Component = "button", className, ...rest }, ref) => (
<li className="navdsi-dropdown__list-item">
<Component
{...rest}
ref={ref}
className={cl(
"navdsi-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className
)}
/>
</li>
)
);
export default Item;
@@ -0,0 +1,27 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import Item, { ItemType } from "./Item";
export interface ListProps extends React.HTMLAttributes<HTMLUListElement> {
/**
* Menu list content
*/
children: React.ReactNode;
}
export interface ListType
extends React.ForwardRefExoticComponent<
ListProps & React.RefAttributes<HTMLUListElement>
> {
Item: ItemType;
}
const List = forwardRef(({ className, children, ...rest }, ref) => (
<ul {...rest} ref={ref} className={cl("navdsi-dropdown__list", className)}>
{children}
</ul>
)) as ListType;
List.Item = Item;
export default List;
@@ -0,0 +1,53 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { Popover } from "@navikt/ds-react";
import List, { ListType } from "./List";
import GroupedList, { GroupedListType } from "./GroupedList";
import { DropdownContext } from "../Dropdown";
interface MenuProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* Dropdown content
*/
children: React.ReactNode;
}
export interface MenuType<Props = MenuProps>
extends React.ForwardRefExoticComponent<
Props & React.RefAttributes<HTMLDivElement>
> {
List: ListType;
GroupedList: GroupedListType;
}
const Menu = forwardRef<HTMLDivElement, MenuProps>(
({ className, ...rest }, ref) => {
const context = useContext(DropdownContext);
if (!context) {
console.warn("Dropdown.Menu has to be wrapped in <Dropdown />");
return null;
}
const { isOpen, anchorEl, setIsOpen } = context;
return (
<Popover
{...rest}
ref={ref}
placement="bottom-end"
arrow={false}
className={cl("navdsi-dropdown__menu", className)}
offset={-4}
anchorEl={anchorEl}
open={isOpen}
onClose={() => setIsOpen(false)}
/>
);
}
) as MenuType;
Menu.List = List;
Menu.GroupedList = GroupedList;
export default Menu;
@@ -0,0 +1,42 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { DropdownContext } from ".";
export interface ToggleProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* Button content
*/
children: React.ReactNode;
}
export type ToggleType = React.ForwardRefExoticComponent<
ToggleProps & React.RefAttributes<HTMLButtonElement>
>;
const Toggle: ToggleType = forwardRef(({ className, ...rest }, ref) => {
const context = useContext(DropdownContext);
if (!context) {
console.warn("Dropdown.Toggle has to be wrapped in <Dropdown />");
return null;
}
const { setAnchorEl, setIsOpen, isOpen } = context;
return (
<button
{...rest}
ref={ref}
onClick={(e) => {
setAnchorEl(e.currentTarget);
setIsOpen((isOpen) => !isOpen);
}}
aria-expanded={isOpen}
aria-haspopup="menu"
className={cl("navdsi-dropdown__toggle", className)}
/>
);
});
export default Toggle;
@@ -0,0 +1,2 @@
export { default as Dropdown } from "./Dropdown";
export * from "./Dropdown";
@@ -0,0 +1,34 @@
import React from "react";
import { Heading } from "@navikt/ds-react";
import { Dropdown } from "..";
import { Divider } from "../..";
export default {
title: "ds-react-internal/dropdown",
component: Dropdown,
};
export const All = () => (
<>
<Heading level="1" size="xlarge">
Dropdown menu
</Heading>
<Dropdown>
<Dropdown.Toggle>Toggle</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Menu.GroupedList>
<Dropdown.Menu.GroupedList.Heading>
Systemer og oppslagsverk
</Dropdown.Menu.GroupedList.Heading>
<Dropdown.Menu.GroupedList.Item>Gosys</Dropdown.Menu.GroupedList.Item>
</Dropdown.Menu.GroupedList>
<Divider />
<Dropdown.Menu.List>
<Dropdown.Menu.List.Item>Gosys</Dropdown.Menu.List.Item>
<Dropdown.Menu.List.Item>Psys</Dropdown.Menu.List.Item>
</Dropdown.Menu.List>
</Dropdown.Menu>
</Dropdown>
</>
);
+12 -10
View File
@@ -1,32 +1,34 @@
import React, { forwardRef, HTMLAttributes } from "react";
import HeaderTitle, { HeaderTitleType } from "./HeaderTitle";
import HeaderUser, { HeaderUserType } from "./HeaderUser";
import HeaderButton, { HeaderButtonType } from "./HeaderButton";
import HeaderUserButton, { HeaderUserButtonType } from "./HeaderUserButton";
import cl from "classnames";
export interface HeaderProps extends HTMLAttributes<HTMLElement> {
/**
* Component content
* Header content
*/
children?: React.ReactNode;
children: React.ReactNode;
}
interface HeaderComponent
extends React.ForwardRefExoticComponent<
HeaderProps & React.RefAttributes<HTMLDivElement>
HeaderProps & React.RefAttributes<HTMLElement>
> {
Title: HeaderTitleType;
User: HeaderUserType;
Button: HeaderButtonType;
UserButton: HeaderUserButtonType;
}
const Header = forwardRef<HTMLElement, HeaderProps>(
({ children, className, ...rest }, ref) => (
<header ref={ref} className={cl("navdsi-header", className)} {...rest}>
{children}
</header>
)
) as HeaderComponent;
const Header = forwardRef(({ className, ...rest }, ref) => (
<header {...rest} ref={ref} className={cl("navdsi-header", className)} />
)) as HeaderComponent;
Header.Title = HeaderTitle;
Header.User = HeaderUser;
Header.Button = HeaderButton;
Header.UserButton = HeaderUserButton;
export default Header;
@@ -0,0 +1,28 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { OverridableComponent } from "@navikt/ds-react";
export interface HeaderButtonProps
extends React.AnchorHTMLAttributes<HTMLButtonElement> {
/**
* Application Button
*/
children: React.ReactNode;
}
export type HeaderButtonType = OverridableComponent<
HeaderButtonProps,
HTMLButtonElement
>;
const HeaderButton: HeaderButtonType = forwardRef(
({ as: Component = "button", className, ...rest }, ref) => (
<Component
{...rest}
ref={ref}
className={cl("navdsi-header__button", className)}
/>
)
);
export default HeaderButton;
@@ -1,9 +1,9 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { Heading, OverridableComponent } from "@navikt/ds-react";
import { OverridableComponent } from "@navikt/ds-react";
export interface HeaderTitleProps
extends React.HTMLAttributes<HTMLHeadingElement> {
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
/**
* Application title
*/
@@ -16,16 +16,20 @@ export type HeaderTitleType = OverridableComponent<
>;
const HeaderTitle: HeaderTitleType = forwardRef(
({ as = "h1", children, className, ...rest }, ref) => (
<Heading
({ as: Component = "a", children, className, ...rest }, ref) => (
<Component
{...rest}
ref={ref}
size="xsmall"
as={as}
className={cl("navdsi-header__title", className)}
className={cl(
"navdsi-header__title",
"navds-heading",
`navds-heading--xsmall`,
className
)}
>
<span>{children}</span>
</Heading>
</Component>
)
);
@@ -4,13 +4,13 @@ import { BodyShort, Detail } from "@navikt/ds-react";
export interface HeaderUserProps extends HTMLAttributes<HTMLDivElement> {
/**
* user name
* User name
*/
name: string;
/**
* user ident
* User description
*/
ident: string;
description?: string;
}
export type HeaderUserType = React.ForwardRefExoticComponent<
@@ -18,12 +18,18 @@ export type HeaderUserType = React.ForwardRefExoticComponent<
>;
const HeaderUser = forwardRef<HTMLDivElement, HeaderUserProps>(
({ className, name, ident, ...rest }, ref) => (
({ className, name, description, ...rest }, ref) => (
<div {...rest} ref={ref} className={cl("navdsi-header__user", className)}>
<BodyShort size="small" className="navdsi-header__name">
{name}
</BodyShort>
<Detail size="small">{ident}</Detail>
<span>
<BodyShort size="small" as="div">
{name}
</BodyShort>
{description && (
<Detail size="small" as="div">
{description}
</Detail>
)}
</span>
</div>
)
);
@@ -0,0 +1,48 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { OverridableComponent } from "@navikt/ds-react";
import { BodyShort, Detail } from "@navikt/ds-react";
import { Expand } from "@navikt/ds-icons";
import HeaderButton from "./HeaderButton";
export interface HeaderUserButtonProps
extends React.AnchorHTMLAttributes<HTMLButtonElement> {
/**
* User name
*/
name: string;
/**
* User description
*/
description?: string;
}
export type HeaderUserButtonType = OverridableComponent<
HeaderUserButtonProps,
HTMLButtonElement
>;
const HeaderUserButton: HeaderUserButtonType = forwardRef(
({ as, name, description, className, ...rest }, ref) => (
<HeaderButton
{...rest}
as={as}
ref={ref}
className={cl("navdsi-header__user-button", className)}
>
<div>
<BodyShort size="small" as="div">
{name}
</BodyShort>
{description && (
<Detail size="small" as="div">
{description}
</Detail>
)}
</div>
<Expand />
</HeaderButton>
)
);
export default HeaderUserButton;
@@ -1,6 +1,2 @@
export { default as Header } from "./Header";
export * from "./Header";
export { default as HeaderTitle } from "./HeaderTitle";
export * from "./HeaderTitle";
export { default as HeaderUser } from "./HeaderUser";
export * from "./HeaderUser";
@@ -1,67 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Header, HeaderTitle, HeaderUser } from "../../index.ts";
<Meta title="ds-react-internal/header/intro" />
# Hvordan ta i bruk Header
Denne header-komponenten vil forgå en del endringer og er for det meste nå
bare en enkel wrapper med lit enkel styling. Bruk på egen risiko
```jsx
<Header>
<Header.Title>NAV Sykepenger</Header.Title>
<Header.User name="Kong Harald" ident="D123456" />
</Header>
```
<Canvas>
<Header>
<Header.Title>NAV Sykepenger</Header.Title>
<Header.User name="Kong Harald" ident="D123456" />
</Header>
</Canvas>
## Uten innhold (wrapper)
```jsx
<Header></Header>
```
<Canvas>
<Header />
</Canvas>
## Tittel, men ikke heading (h-element)
```jsx
<Header>
<Header.Title>Tittel</Header.Title>
</Header>
```
<Canvas>
<Header>
<Header.Title as="span">Tittel</Header.Title>
</Header>
</Canvas>
## Heading med link
Focus-stylingen her er bare placeholder for nå
```jsx
<Header>
<Header.Title as="a" href="/#home">
Tittel med lenke
</Header.Title>
</Header>
```
<Canvas>
<Header>
<Header.Title as="a" href="/#home">
Tittel med lenke
</Header.Title>
</Header>
</Canvas>
@@ -1,6 +1,8 @@
import React from "react";
import { HashRouter as Router, Link } from "react-router-dom";
import { BodyLong, BodyShort, Detail, Heading } from "@navikt/ds-react";
import { Header } from "..";
import { Expand, System, ExternalLink } from "@navikt/ds-icons";
import { Divider, Dropdown } from "../..";
export default {
title: "ds-react-internal/header",
@@ -8,45 +10,148 @@ export default {
};
export const All = () => (
<div>
<>
<Heading level="1" size="xlarge">
Header for interne flater
</Heading>
<Heading level="2" size="medium">
Title
</Heading>
<Header>
<Header.Title>NAV Sykepenger</Header.Title>
<Header.User name="Kong Harald" ident="D123456" />
<Header.Title href="/#home">Tittel med lenke</Header.Title>
</Header>
<h1>Uten innhold</h1>
<Header />
<h1>Title</h1>
<Heading level="2" size="medium">
Title as h1
</Heading>
<Header>
<Header.Title>Tittel</Header.Title>
<Header.Title as="h1">Tittel</Header.Title>
</Header>
<h1>Title as span</h1>
<Heading level="2" size="medium">
User
</Heading>
<Header>
<Header.Title as="span">Tittel</Header.Title>
<Header.Title href="/#home">NAV Sykepenger</Header.Title>
<Header.User name="Kong Harald" style={{ marginLeft: "auto" }} />
</Header>
<h1>Title as link</h1>
<Heading level="2" size="medium">
User with description
</Heading>
<Header>
<Header.Title as="a" href="/#home">
Tittel med lenke
</Header.Title>
<Header.Title href="/#home">NAV Sykepenger</Header.Title>
<Dropdown>
<Header.Button as={Dropdown.Toggle} style={{ marginLeft: "auto" }}>
<System
style={{ fontSize: "1.5rem" }}
title="Systemer og oppslagsverk"
/>
</Header.Button>
<Dropdown.Menu>
<Dropdown.Menu.List>
<Dropdown.Menu.List.Item>
<span>A.Inntekt</span>
<ExternalLink style={{ fontSize: "0.875rem" }} />
</Dropdown.Menu.List.Item>
<Dropdown.Menu.List.Item>
<span>Aa-registeret</span>
<ExternalLink style={{ fontSize: "0.875rem" }} />
</Dropdown.Menu.List.Item>
<Dropdown.Menu.List.Item>
<span>Gosys</span>
<ExternalLink style={{ fontSize: "0.875rem" }} />
</Dropdown.Menu.List.Item>
</Dropdown.Menu.List>
</Dropdown.Menu>
</Dropdown>
<Header.User name="Kong Harald" description="D123456" />
</Header>
<h1>Title as react-router link</h1>
<Router>
<Header>
<Header.Title as={Link} to="/home">
Tittel med lenke
</Header.Title>
</Header>
</Router>
<Heading level="2" size="medium">
Systems and user menu
</Heading>
<Full />
<h1>Title + User</h1>
<Header>
<Header.Title>NAV Sykepenger</Header.Title>
<Header.User name="Kong Harald" ident="D123456" />
</Header>
</div>
<Heading level="2" size="medium">
Initials
</Heading>
<Initials />
</>
);
const Full = () => (
<Header>
<Header.Title href="/#home">NAV Sykepenger</Header.Title>
<Dropdown>
<Header.Button as={Dropdown.Toggle} style={{ marginLeft: "auto" }}>
<System
style={{ fontSize: "1.5rem" }}
title="Systemer og oppslagsverk"
/>
</Header.Button>
<Dropdown.Menu>
<Dropdown.Menu.GroupedList>
<Dropdown.Menu.GroupedList.Heading>
Systemer og oppslagsverk
</Dropdown.Menu.GroupedList.Heading>
<Dropdown.Menu.GroupedList.Item>
A.Inntekt
</Dropdown.Menu.GroupedList.Item>
</Dropdown.Menu.GroupedList>
</Dropdown.Menu>
</Dropdown>
<Dropdown>
<Header.UserButton
as={Dropdown.Toggle}
name="Kong Harald"
description="Enhet: Skien"
/>
<Dropdown.Menu>
<Dropdown.Menu.List>
<Dropdown.Menu.List.Item onClick={() => console.log("logg ut")}>
Logg ut
</Dropdown.Menu.List.Item>
</Dropdown.Menu.List>
</Dropdown.Menu>
</Dropdown>
</Header>
);
const Initials = () => (
<Header>
<Header.Title href="/#home">NAV Sykepenger</Header.Title>
<Dropdown>
<Header.Button as={Dropdown.Toggle} style={{ marginLeft: "auto" }}>
<BodyShort size="small" title="Kong Harald">
KH
</BodyShort>
<Expand />
</Header.Button>
<Dropdown.Menu>
<div>
<BodyLong size="small" as="div">
Kong Harald 16px
</BodyLong>
<Detail size="small" as="div">
<div>Ident nr 14px</div>
<div>Enhet: Skien</div>
</Detail>
</div>
<Divider />
<Dropdown.Menu.List>
<Dropdown.Menu.List.Item as="a" href="/#settings">
Innstillinger
</Dropdown.Menu.List.Item>
<Dropdown.Menu.List.Item onClick={() => console.log("logg ut")}>
Logg ut
</Dropdown.Menu.List.Item>
</Dropdown.Menu.List>
</Dropdown.Menu>
</Dropdown>
</Header>
);
+2
View File
@@ -1 +1,3 @@
export * from "./divider";
export * from "./dropdown";
export * from "./header";
+10
View File
@@ -19,6 +19,16 @@ yarn storybook
[http://localhost:6006](http://localhost:6006) (port auto-incrementeres hvis den allerede er i bruk av en annen server)
### Yarn install med Mac M1 chip
For at `yarn install` skal funke på Mac med M1 chip krever sharp-pakken at du har "libvps" installert globalt. Libvps krever også gcc og xcode build tools CLI. Dette kan installeres med følgende kommandoer:
```sh
xcode-select --install
brew install gcc
brew reinstall vips
```
## Utviklingsmiljø
Vi tar nå i bruk storybook [https://storybook.js.org/](https://storybook.js.org/) som utviklermiljø.
+1 -1
View File
@@ -18,7 +18,7 @@
## Innhold
Dette repoet inneholder følgende:
Repoet inneholder følgende:
- [Alle felleskomponenter](https://github.com/navikt/nav-frontend-moduler/tree/master/packages/) i NAVs frontend-rammeverk forvaltet av designsystemet
- [Felleskomponenter V2 (WIP)](https://github.com/navikt/nav-frontend-moduler/tree/master/@navikt/) oppdaterte og scopede pakker for en bedre brukeropplevelse
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "independent",
"command": {
"publish": {
"registry": "http://registry.npmjs.org/",
"registry": "https://registry.npmjs.org/",
"npmClient": "npm",
"ignoreChanges": ["*.md", "*.mdx", "*.story.tsx", "*.stories.tsx"],
"message": "Lerna versionbump [ci skip]"
-100
View File
@@ -1,100 +0,0 @@
/* eslint-disable strict */
"use strict";
const gulp = require("gulp");
const through = require("through2");
const newer = require("gulp-newer");
const plumber = require("gulp-plumber");
const gutil = require("gulp-util");
const path = require("path");
const chalk = require("chalk");
const cssfont64 = require("gulp-cssfont64-formatter");
const configureSvgIcon = require("react-svg-icon-generator-fork").default;
const fonts = "./packages/node_modules/*/assets/**/*.woff";
const dest = "../../packages";
let assetsEx;
let srcFragment;
if (path.win32 === path) {
assetsEx = /(packages\\[^/]+)\\assets\\/;
srcFragment = "$1\\src\\";
} else {
assetsEx = new RegExp("(packages/[^/]+)/assets/");
srcFragment = "$1/src/";
}
function mapSrcToDest(filepath) {
return filepath.replace(assetsEx, srcFragment);
}
function fixErrorHandling() {
return plumber({
errorHandler: (err) => gutil.log(err.stack),
});
}
function onlyNewFiles(map) {
return newer({ map });
}
function logCompiling() {
return through.obj((file, enc, callback) => {
gutil.log("Compiling", `'${chalk.cyan(file.path)}'...`);
callback(null, file);
});
}
function renameUsingMapper(mapper) {
return through.obj((file, enc, callback) => {
file._path = file.path; // eslint-disable-line no-underscore-dangle, no-param-reassign
file.path = mapper(file.path); // eslint-disable-line no-param-reassign
callback(null, file);
});
}
function cssFontfile(filename, mimetype, file64, format) {
const fontFamiliy = "Source Sans Pro"; // all fonts at this point is Source sans pro
const fontWeight = filename.replace(/\D/g, "") || "400"; // 400 is called regular
const fontStyle = filename.indexOf("italic") >= 0 ? "italic" : "normal";
// eslint-disable-next-line max-len
return `@font-face { font-family: '${fontFamiliy}'; font-weight: ${fontWeight}; font-style: ${fontStyle}; src: url(data:${mimetype};base64,${file64}) format("${format}");}`;
}
function buildCssfonts() {
return gulp
.src(fonts)
.pipe(fixErrorHandling())
.pipe(onlyNewFiles(mapSrcToDest))
.pipe(logCompiling())
.pipe(cssfont64({ formatter: cssFontfile, extention: "less" }))
.pipe(renameUsingMapper(mapSrcToDest))
.pipe(gulp.dest(dest));
}
configureSvgIcon({
destination: path.join(
__dirname,
"packages",
"node_modules",
"nav-frontend-ikoner-assets",
"src",
"index.js"
),
svgDir: path.join(
__dirname,
"packages",
"node_modules",
"nav-frontend-ikoner-assets",
"assets"
),
keepFillColor: true,
});
gulp.task("default", gulp.series("build"));
gulp.task("buildicons", gulp.series("svg-icon"));
gulp.task("buildfonts", gulp.series(buildCssfonts));
-24
View File
@@ -1,24 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "esnext",
"moduleResolution": "node",
"allowJs": false,
"declaration": true,
"noImplicitAny": false,
"strictNullChecks": true,
"removeComments": false,
"preserveConstEnums": true,
"sourceMap": true,
"jsx": "react",
"lib": ["DOM", "es2015", "es2016", "es2017"]
},
"include": ["../../packages/**/src/*"],
"exclude": [
"node_modules",
"**/*-spec.js",
"**/*-test.js",
"**/*.less",
"documentation"
]
}
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "independent",
"command": {
"publish": {
"registry": "http://registry.npmjs.org/",
"registry": "https://registry.npmjs.org/",
"npmClient": "npm",
"ignoreChanges": ["*.md", "*.mdx", "*.story.tsx", "*.stories.tsx"],
"message": "Lerna versionbump [ci skip]"
-64
View File
@@ -1,64 +0,0 @@
const glob = require("glob");
const fs = require("fs");
const inquirer = require("inquirer");
const semver = require("semver");
function readfile(file) {
return JSON.parse(fs.readFileSync(file, "utf-8"));
}
function getModules() {
return new Promise((resolve, reject) => {
glob("./packages/node_modules/**/package.json", {}, (err, files) => {
if (err) {
reject(err);
} else {
const filesdata = files.map((file) => ({
location: file,
pkg: readfile(file),
}));
resolve(filesdata);
}
});
});
}
function bumpVersions(bump) {
return (modules) => {
modules.forEach((module) => {
module.pkg.version = semver.inc(module.pkg.version, bump); // eslint-disable-line no-param-reassign
});
return modules;
};
}
function saveToDisk(modules) {
modules.forEach((module) => {
const location = module.location;
const pkg = module.pkg;
const content = `${JSON.stringify(pkg, null, 2)}\n`;
console.log("Bumped", pkg.name, pkg.version); // eslint-disable-line no-console
fs.writeFileSync(location, content, "utf-8");
});
}
inquirer
.prompt([
{
type: "list",
name: "bump",
message: "Bump?",
choices: ["patch", "minor", "major"],
},
])
.then((answers) => {
getModules()
.then(bumpVersions(answers.bump))
.then(saveToDisk)
.catch((error) => {
console.log("error", error); // eslint-disable-line no-console
});
});
@@ -1,85 +0,0 @@
const glob = require("glob");
const fs = require("fs");
const extend = require("extend");
const utils = require("./utils");
const globalPackage = require("../../package.json");
const globalDeps = extend(
{},
globalPackage.devDependencies,
globalPackage.dependencies
);
function getModules() {
return new Promise((resolve, reject) => {
glob("./packages/**/package.json", {}, (err, files) => {
if (err) {
reject(err);
} else {
resolve(files.filter((file) => file.indexOf("node_modules") === -1));
}
});
});
}
function fixDependencies(pkg, section) {
if (!pkg[section]) {
return;
}
// eslint-disable-next-line no-param-reassign
pkg[section] = utils
.entries(pkg[section])
.map((entry) => {
const depName = entry.key;
if (!globalDeps[depName]) {
return entry;
}
return { key: depName, value: globalDeps[depName] };
})
.reduce((deps, entry) => extend(deps, { [entry.key]: entry.value }), {});
}
function addModuleVersions(files) {
files.forEach((file) => {
const pkg = JSON.parse(fs.readFileSync(file, "utf-8"));
globalDeps[pkg.name] = `^${pkg.version}`;
});
return files;
}
function injectGlobalDependencies(files) {
return files.map((file) => {
const pkg = JSON.parse(fs.readFileSync(file, "utf-8"));
fixDependencies(pkg, "dependencies");
fixDependencies(pkg, "devDependencies");
fixDependencies(pkg, "peerDependencies");
return {
location: file,
pkg,
};
});
}
function saveToDisk(modules) {
modules.forEach((module) => {
const location = module.location;
const pkg = module.pkg;
const content = `${JSON.stringify(pkg, null, 2)}\n`;
fs.writeFileSync(location, content, "utf-8");
});
}
getModules()
.then(addModuleVersions)
.then(injectGlobalDependencies)
.then(saveToDisk)
.catch((error) => {
console.log("error", error); // eslint-disable-line no-console
});
-54
View File
@@ -1,54 +0,0 @@
const path = require("path");
const fs = require("fs");
const glob = require("glob");
const markdownMagic = require("markdown-magic");
const mustache = require("mustache");
const dfs = require("depth-first").default;
mustache.tags = ["<%", "%>"];
const disclaimerMD = fs.readFileSync(
path.join(__dirname, "DISCLAIMER.md"),
"utf-8"
);
function createConfig(moduleName, edges) {
return {
transforms: {
DISCLAIMER() {
const renderdata = { name: moduleName };
return mustache.render(disclaimerMD, renderdata);
},
INSTALL() {
const dependencies = dfs(edges, moduleName).sort().join(" ");
return [
"### Installering:",
"```",
`npm install ${dependencies} --save`,
"```",
].join("\n");
},
},
};
}
glob("./packages/**/package.json", { dot: true }, (err, files) => {
const pkgs = files.map((file) => JSON.parse(fs.readFileSync(file, "utf-8")));
const edges = pkgs
.map((pkg) => [pkg.name, Object.keys(pkg.peerDependencies || {})])
.reduce(
(arr, [pkgName, pkgDependencies]) => [
...arr,
...pkgDependencies.map((dependency) => [pkgName, dependency]),
],
[]
);
pkgs.forEach((pkg) => {
const pkgName = pkg.name;
const config = createConfig(pkgName, edges);
const MD = path.join(__dirname, "../..", "packages", pkgName, "README.md");
// eslint-disable-next-line no-console
markdownMagic(MD, config, (error) => error && console.log("err", error));
});
});
-65
View File
@@ -1,65 +0,0 @@
/* eslint-disable strict */
"use strict";
const extend = require("extend");
function capitalize(str) {
return str && str[0].toUpperCase() + str.slice(1);
}
function camelcase(str) {
return str && str.split(/\W/).map(capitalize).join("");
}
function kebabcase(str) {
return str && str.split(/\W/).join("-");
}
function entries(obj) {
return Object.keys(obj).map((key) => ({ key, value: obj[key] }));
}
function allCompleted(promises) {
return new Promise((resolve, _reject) => {
let unresolvedPromises = promises.length;
const result = new Array(promises.length);
promises.forEach((promise, index) =>
promise
.then((res) => {
result[index] = res;
unresolvedPromises -= 1;
})
.catch((res) => {
result[index] = res;
unresolvedPromises -= 1;
})
.then(() => {
if (unresolvedPromises === 0) {
resolve(result);
}
})
);
});
}
function parsetag(tagstring) {
const regex = /^(.+)[-@]((?:\d+\.?){3})$/;
const match = regex.exec(tagstring);
if (!match) {
throw new Error(`Tag did not conform to expected format: ${tagstring}`);
}
return { name: match[1], version: match[2] };
}
function allDependencies(pkg) {
const dependencies = pkg.dependencies || {};
const peerDependencies = pkg.peerDependencies || {};
const devDependencies = pkg.devDependencies || {};
return extend({}, devDependencies, peerDependencies, dependencies);
}
module.exports = {
capitalize,
camelcase,
kebabcase,
entries,
allCompleted,
parsetag,
allDependencies,
};
-148
View File
@@ -1,148 +0,0 @@
/* eslint-disable strict, no-console */
"use strict";
const fs = require("fs");
const glob = require("glob");
const chalk = require("chalk");
const extend = require("extend");
const semver = require("semver");
semver.clean = (version, loose) => {
// Monkeypatch
// var s = semver.parse(version.trim().replace(/^[=v]+]/, ''), loose); // Originalkode
const s = semver.parse(version.trim().replace(/^[=v^~]+/, ""), loose);
return s ? s.version : null;
};
let hasError = false;
const pkgGlob = "./packages/node_modules/**/package.json";
function objectIntersection(obj1, obj2) {
return Object.keys(obj1).filter({}.hasOwnProperty.bind(obj2));
}
function verifySameValue(obj1, obj2, errorMessage) {
return (key) => {
if (
obj1[key] !== obj2[key] &&
!semver.satisfies(semver.clean(obj1[key]), obj2[key])
) {
console.log(
`${chalk.red("ERROR::")} ${errorMessage(key, obj1[key], obj2[key])}`
);
hasError = true;
}
};
}
const internalMismatch = (key, val1, val2) =>
`Found internal mismatch for ${key}. ${val1} !== ${val2}`;
const globalMismatch = (key, val1, val2) =>
`Found global mismatch for ${key}. ${val1} !== ${val2}`;
const interMismatch = (key, val1, val2) =>
`Found inter-dependency mismatch for ${key}. ${val1} !== ${val2}`;
function verifyRelaxedVersions(dependencies) {
return Object.keys(dependencies)
.map((dependency) => [dependency, dependencies[dependency]])
.forEach((dependency) => {
const name = dependency[0];
const version = dependency[1];
if (version[0] !== "^") {
console.log(
`${chalk.red(
"ERROR::"
)} Found non-relaxed version-range for ${name}:${version}`
);
hasError = true;
}
});
}
function analyzeDependenciesOf(pkg, depMap) {
if (!depMap) {
depMap = {}; // eslint-disable-line no-param-reassign
}
// Check that dependencies in pkg use same version in all dependency-sections
const dependencies = pkg.dependencies || {};
const peerDependencies = pkg.peerDependencies || {};
const devDependencies = pkg.devDependencies || {};
objectIntersection(dependencies, peerDependencies).forEach(
verifySameValue(dependencies, peerDependencies, internalMismatch)
); // eslint-disable-line max-len
objectIntersection(dependencies, devDependencies).forEach(
verifySameValue(dependencies, devDependencies, internalMismatch)
); // eslint-disable-line max-len
objectIntersection(devDependencies, peerDependencies).forEach(
verifySameValue(devDependencies, peerDependencies, internalMismatch)
); // eslint-disable-line max-len
objectIntersection(dependencies, depMap).forEach(
verifySameValue(dependencies, depMap, interMismatch)
);
objectIntersection(devDependencies, depMap).forEach(
verifySameValue(devDependencies, depMap, interMismatch)
);
objectIntersection(depMap, peerDependencies).forEach(
verifySameValue(depMap, peerDependencies, interMismatch)
);
verifyRelaxedVersions(peerDependencies);
return {
name: pkg.name,
version: pkg.version,
dependencies: extend({}, dependencies, peerDependencies, devDependencies),
};
}
console.log(`Checking package: ${chalk.cyan("./package.json")}`);
const globalPkg = analyzeDependenciesOf(
JSON.parse(fs.readFileSync("./package.json"))
);
console.log("");
glob(pkgGlob, { dot: true }, (err, files) => {
const pkgs = files.map((file) => ({
file,
content: JSON.parse(fs.readFileSync(file, "utf-8")),
}));
const depMap = pkgs.reduce(
(map, data) => extend(map, { [data.content.name]: data.content.version }),
{}
);
pkgs.forEach((data) => {
console.log(`Checking package: ${chalk.cyan(data.file)}`);
// Name check
const pkgName = data.content.name;
if (data.file.indexOf(pkgName) === -1) {
console.log(
`${chalk.red("ERROR:")} Found name mismatch in ${
data.file
}. Packagename was: ${pkgName}`
);
hasError = true;
}
const pkg = analyzeDependenciesOf(data.content, depMap);
Object.keys(pkg.dependencies)
.filter((key) => !key.startsWith("nav-frontend-"))
.forEach(
verifySameValue(
pkg.dependencies,
globalPkg.dependencies,
globalMismatch
)
);
console.log("");
});
hasError && process.exit(1); // eslint-disable-line no-unused-expressions
});