@primer/components 33.0.0-rc.9f3670b7 → 33.0.0-rc.cface7dc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. package/.github/workflows/statuses.yml +32 -0
  2. package/.gitignore +1 -0
  3. package/CHANGELOG.md +2 -0
  4. package/docs/src/component-checklist.js +10 -2
  5. package/lib/ActionMenu2.d.ts +6 -3
  6. package/lib/Autocomplete/Autocomplete.d.ts +2 -1
  7. package/lib/Autocomplete/AutocompleteInput.d.ts +2 -1
  8. package/lib/Button/Button.d.ts +2 -2
  9. package/lib/Button/ButtonClose.d.ts +2 -2
  10. package/lib/Button/ButtonDanger.d.ts +2 -2
  11. package/lib/Button/ButtonInvisible.d.ts +2 -2
  12. package/lib/Button/ButtonOutline.d.ts +2 -2
  13. package/lib/Button/ButtonPrimary.d.ts +2 -2
  14. package/lib/CircleOcticon.d.ts +35 -35
  15. package/lib/Dialog.d.ts +37 -37
  16. package/lib/Dropdown.d.ts +6 -6
  17. package/lib/DropdownMenu/DropdownButton.d.ts +6 -3
  18. package/lib/FilterList.d.ts +1 -1
  19. package/lib/Position.d.ts +4 -4
  20. package/lib/SelectMenu/SelectMenu.d.ts +11 -10
  21. package/lib/SelectMenu/SelectMenuItem.d.ts +1 -1
  22. package/lib/SelectMenu/SelectMenuModal.d.ts +1 -1
  23. package/lib/TextInputWithTokens.d.ts +2 -1
  24. package/lib/Token/AvatarToken.d.ts +1 -1
  25. package/lib/Token/IssueLabelToken.d.ts +1 -1
  26. package/lib/Token/Token.d.ts +1 -1
  27. package/lib-esm/ActionMenu2.d.ts +6 -3
  28. package/lib-esm/Autocomplete/Autocomplete.d.ts +2 -1
  29. package/lib-esm/Autocomplete/AutocompleteInput.d.ts +2 -1
  30. package/lib-esm/Button/Button.d.ts +2 -2
  31. package/lib-esm/Button/ButtonClose.d.ts +2 -2
  32. package/lib-esm/Button/ButtonDanger.d.ts +2 -2
  33. package/lib-esm/Button/ButtonInvisible.d.ts +2 -2
  34. package/lib-esm/Button/ButtonOutline.d.ts +2 -2
  35. package/lib-esm/Button/ButtonPrimary.d.ts +2 -2
  36. package/lib-esm/CircleOcticon.d.ts +35 -35
  37. package/lib-esm/Dialog.d.ts +37 -37
  38. package/lib-esm/Dropdown.d.ts +6 -6
  39. package/lib-esm/DropdownMenu/DropdownButton.d.ts +6 -3
  40. package/lib-esm/FilterList.d.ts +1 -1
  41. package/lib-esm/Position.d.ts +4 -4
  42. package/lib-esm/SelectMenu/SelectMenu.d.ts +11 -10
  43. package/lib-esm/SelectMenu/SelectMenuItem.d.ts +1 -1
  44. package/lib-esm/SelectMenu/SelectMenuModal.d.ts +1 -1
  45. package/lib-esm/TextInputWithTokens.d.ts +2 -1
  46. package/lib-esm/Token/AvatarToken.d.ts +1 -1
  47. package/lib-esm/Token/IssueLabelToken.d.ts +1 -1
  48. package/lib-esm/Token/Token.d.ts +1 -1
  49. package/package-lock.json +303 -255
  50. package/package.json +4 -2
  51. package/script/component-status-project/build.ts +100 -0
  52. package/script/component-status-project/deploy.rb +142 -0
  53. package/stats.html +1 -1
  54. package/tsconfig.build.json +1 -1
  55. package/tsconfig.json +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/components",
3
- "version": "33.0.0-rc.9f3670b7",
3
+ "version": "33.0.0-rc.cface7dc",
4
4
  "description": "Primer react components",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib-esm/index.js",
@@ -91,6 +91,7 @@
91
91
  "@types/jest-axe": "3.5.3",
92
92
  "@types/lodash.isempty": "4.4.6",
93
93
  "@types/lodash.isobject": "3.0.6",
94
+ "@types/node": "16.11.11",
94
95
  "@typescript-eslint/eslint-plugin": "4.31.2",
95
96
  "@typescript-eslint/parser": "4.26.1",
96
97
  "@wojtekmaj/enzyme-adapter-react-17": "0.6.3",
@@ -116,6 +117,7 @@
116
117
  "eslint-plugin-primer-react": "0.7.0",
117
118
  "eslint-plugin-react": "7.24.0",
118
119
  "eslint-plugin-react-hooks": "4.2.0",
120
+ "front-matter": "4.0.2",
119
121
  "jest": "27.0.4",
120
122
  "jest-axe": "5.0.1",
121
123
  "jest-styled-components": "6.3.4",
@@ -137,7 +139,7 @@
137
139
  "storybook-addon-performance": "0.16.1",
138
140
  "styled-components": "4.4.1",
139
141
  "ts-toolbelt": "9.6.0",
140
- "typescript": "4.2.2"
142
+ "typescript": "4.4.4"
141
143
  },
142
144
  "peerDependencies": {
143
145
  "react": "^17.0.0",
@@ -0,0 +1,100 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
5
+ const fm = require('front-matter') // FIXME after this bugfix is merged https://github.com/jxson/front-matter/pull/77
6
+
7
+ const sourceDirectory = path.resolve(__dirname, '../../docs/content/')
8
+ const outputDir = path.resolve(__dirname, '../../dist/')
9
+
10
+ type ComponentStatus = {
11
+ [component: string]: string
12
+ }
13
+
14
+ /**
15
+ * Extracts the component status for each file in the given directory.
16
+ *
17
+ * @param filenames Array of filenames to read front-matter from
18
+ * @param dir Absolute path to directory containing files
19
+ * @returns A promise that resolves to an array containing outcome of file front-matter extraction
20
+ */
21
+ function getComponentStatuses(filenames: string[], dir: string) {
22
+ const promises: Promise<ComponentStatus | null>[] = []
23
+
24
+ const handleCallback = (
25
+ filename: string,
26
+ resolve: (value: ComponentStatus | null) => void,
27
+ reject: (value: unknown) => void
28
+ ) => {
29
+ fs.readFile(path.resolve(dir, filename), 'utf-8', (err, content) => {
30
+ if (err) return reject(err)
31
+
32
+ if (fm.test(content)) {
33
+ const {
34
+ attributes: {title, status}
35
+ } = fm(content)
36
+
37
+ if (status) {
38
+ return resolve({[title]: status})
39
+ }
40
+ }
41
+
42
+ resolve(null)
43
+ })
44
+ }
45
+
46
+ for (const filename of filenames) {
47
+ const promise: Promise<ComponentStatus | null> = new Promise((resolve, reject) => {
48
+ return handleCallback(filename, resolve, reject)
49
+ })
50
+ promises.push(promise)
51
+ }
52
+
53
+ return Promise.all(promises)
54
+ }
55
+
56
+ /**
57
+ * Orchestrates the process of reading component status for each file in the given directory.
58
+ *
59
+ * @param dir Directory to source files where status will be extracted from
60
+ * @returns A promise that resolves to an object containing component statuses
61
+ */
62
+ async function readFiles(dir: string) {
63
+ try {
64
+ const dirContents = fs.readdirSync(dir, {withFileTypes: true})
65
+ const filenames = dirContents.filter(dirent => dirent.isFile()).map(dirent => dirent.name)
66
+ const componentStatuses = await getComponentStatuses(filenames, dir)
67
+
68
+ return componentStatuses
69
+ .filter(Boolean)
70
+ .reverse()
71
+ .reduce(
72
+ (acc, file) => ({
73
+ ...acc,
74
+ ...file
75
+ }),
76
+ {}
77
+ )
78
+ } catch (err) {
79
+ throw new Error(`error reading files: ${err}`)
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Writes the component status to the given file.
85
+ */
86
+ async function build() {
87
+ try {
88
+ const componentStatuses = await readFiles(sourceDirectory)
89
+
90
+ if (!fs.existsSync(outputDir)) {
91
+ fs.mkdirSync(outputDir)
92
+ }
93
+
94
+ fs.writeFileSync(`${outputDir}/component-status.json`, JSON.stringify(componentStatuses))
95
+ } catch (error) {
96
+ throw new Error(`error building component status object: ${error}`)
97
+ }
98
+ }
99
+
100
+ build()
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ # Adapted from https://github.com/primer/view_components/blob/main/script/update-statuses-project.rb
3
+ # Usage: script/update-statuses-project
4
+ # frozen_string_literal: true
5
+
6
+ require "graphql/client"
7
+ require "graphql/client/http"
8
+
9
+ statuses = File.read(File.join(File.dirname(__FILE__), "../../dist/component-status.json"))
10
+ statuses_json = JSON.parse(statuses)
11
+
12
+ class QueryExecutionError < StandardError; end
13
+ NOTE_SEPARATOR = " --- "
14
+
15
+ module Github
16
+ GITHUB_ACCESS_TOKEN = ENV.fetch("GITHUB_TOKEN")
17
+ URL = "https://api.github.com/graphql"
18
+ HttpAdapter = GraphQL::Client::HTTP.new(URL) do
19
+ def headers(_)
20
+ {
21
+ "Authorization" => "Bearer #{GITHUB_ACCESS_TOKEN}",
22
+ "User-Agent" => "Ruby"
23
+ }
24
+ end
25
+ end
26
+ Schema = GraphQL::Client.load_schema(HttpAdapter)
27
+ Client = GraphQL::Client.new(schema: Schema, execute: HttpAdapter)
28
+ end
29
+
30
+ # Project is a GraphQL wrapper for interacting with GitHub projects
31
+ class Project
32
+ ProjectQuery = Github::Client.parse <<-'GRAPHQL'
33
+ query {
34
+ repository(owner: "primer", name: "react") {
35
+ project(number: 5) {
36
+ columns(first: 100) {
37
+ nodes {
38
+ name
39
+ id
40
+ databaseId
41
+ cards {
42
+ nodes {
43
+ id
44
+ databaseId
45
+ note
46
+ column {
47
+ name
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ GRAPHQL
57
+
58
+ CreateCard = Github::Client.parse <<-'GRAPHQL'
59
+ mutation($note: String!, $projectColumnId: ID!) {
60
+ addProjectCard(input:{note: $note, projectColumnId: $projectColumnId, clientMutationId: "prc-actions"}) {
61
+ __typename
62
+ }
63
+ }
64
+ GRAPHQL
65
+
66
+ MoveCard = Github::Client.parse <<-'GRAPHQL'
67
+ mutation($cardId: ID!, $columnId: ID!) {
68
+ moveProjectCard(input:{cardId: $cardId, columnId: $columnId, clientMutationId: "prc-actions"}) {
69
+ __typename
70
+ }
71
+ }
72
+ GRAPHQL
73
+
74
+ def self.create_card(note:, column_id:)
75
+ response = Github::Client.query(CreateCard, variables: { note: note, projectColumnId: column_id })
76
+ return unless response.errors.any?
77
+
78
+ raise QueryExecutionError, response.errors[:data].join(", ")
79
+ end
80
+
81
+ def self.move_card(card_id:, column_id:)
82
+ response = Github::Client.query(MoveCard, variables: { cardId: card_id, columnId: column_id })
83
+ return unless response.errors.any?
84
+
85
+ raise(QueryExecutionError, response.errors[:data].join(", "))
86
+ end
87
+
88
+ def self.fetch_columns
89
+ response = Github::Client.query(ProjectQuery)
90
+ return response.data.repository.project.columns unless response.errors.any?
91
+
92
+ raise(QueryExecutionError, response.errors[:data].join(", "))
93
+ end
94
+ end
95
+
96
+ columns = Project.fetch_columns.nodes
97
+
98
+ @column_mapping = {}
99
+ columns.each do |column|
100
+ @column_mapping[column.name.downcase] = column.id
101
+ end
102
+
103
+ @cards = columns.map(&:cards).map(&:nodes).flatten
104
+
105
+ def get_card(name_prefix:)
106
+ @cards.find { |card| card.note.start_with?(name_prefix) }
107
+ end
108
+
109
+ def on_correct_column?(card_id:, status:)
110
+ card = @cards.find { |c| c.id == card_id }
111
+ card.column.name.casecmp(status).zero?
112
+ end
113
+
114
+ def move_card(card_id:, status:)
115
+ column_id = @column_mapping[status.downcase]
116
+
117
+ puts "move card with #{card_id} to #{status} on column #{column_id}"
118
+
119
+ Project.move_card(card_id: card_id, column_id: column_id)
120
+ end
121
+
122
+ def create_card(component_name:, status:)
123
+ column_id = @column_mapping[status.downcase]
124
+
125
+ puts "create card with #{component_name} on #{status} on column #{column_id}"
126
+
127
+ Project.create_card(note: component_name, column_id: column_id)
128
+ end
129
+
130
+ statuses_json.each do |component_name, component_status|
131
+ card = get_card(name_prefix: component_name)
132
+
133
+ if card
134
+ if on_correct_column?(card_id: card.id, status: component_status)
135
+ puts "#{card.id} is on the right column. noop"
136
+ else
137
+ move_card(card_id: card.id, status: component_status)
138
+ end
139
+ else
140
+ create_card(component_name: component_name, status: component_status)
141
+ end
142
+ end